diff --git a/src/vendor/cigraph/.devcontainer/devcontainer.json b/src/vendor/cigraph/.devcontainer/devcontainer.json
deleted file mode 100644
index fc3081d84db..00000000000
--- a/src/vendor/cigraph/.devcontainer/devcontainer.json
+++ /dev/null
@@ -1,40 +0,0 @@
-// For format details, see https://aka.ms/devcontainer.json. For config options, see the
-// README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu
-{
- "name": "igraph dev environment",
-
- // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
- "image": "mcr.microsoft.com/devcontainers/base:jammy",
-
- // Features to add to the dev container. More info: https://containers.dev/features.
- "features": {
- "ghcr.io/rocker-org/devcontainer-features/apt-packages:1": {
- "packages": "build-essential,clang,cmake,cmake-curses-gui,ninja-build,ccache,colordiff,astyle,bison,flex,libxml2-dev,libarpack2-dev,libglpk-dev,libgmp-dev,xmlto,texinfo,source-highlight,libxml2-utils,xsltproc,fop"
- }
- },
-
- // Environment variables containing settings for various tools
- "containerEnv": {
- "CMAKE_GENERATOR": "Ninja",
- "ASAN_OPTIONS": "color=always"
- },
-
- // Use 'forwardPorts' to make a list of ports inside the container available locally.
- // "forwardPorts": [],
-
- // Use 'postCreateCommand' to run commands after the container is created.
- // "postCreateCommand": "uname -a",
-
- // Configure tool-specific properties.
- "customizations": {
- "vscode": {
- "extensions": [
- "ms-vscode.cpptools-extension-pack", // C/C++ and CMake support
- "daohong-emilio.yash" // flex/bison support
- ]
- }
- }
-
- // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
- // "remoteUser": "root"
-}
diff --git a/src/vendor/cigraph/CHANGELOG.md b/src/vendor/cigraph/CHANGELOG.md
index 1fad8213fd6..faa6a6dfa44 100644
--- a/src/vendor/cigraph/CHANGELOG.md
+++ b/src/vendor/cigraph/CHANGELOG.md
@@ -5,6 +5,8 @@
### Changes
- `igraph_community_walktrap()` no longer requires `modularity` and `merges` to be non-NULL when `membership` is non-NULL.
+ - `igraph_isomorphic()` now supports multigraphs.
+ - Shortest path related functions now consistently ignore edges with positive infinite weights.
### Fixed
@@ -16,16 +18,19 @@
- HRG functions now require a graph with at least 3 vertices; previous versions crashed with smaller graphs.
- `igraph_arpack_rssolve()` and `igraph_arpack_rnsolve()`, i.e. the ARPACK interface in igraph, are now interruptible. As a result, several other functions that rely on ARPACK (eigenvector centrality, hub and authority scores, etc.) also became interruptible.
- `igraph_get_shortest_paths_dijkstra()`, `igraph_get_all_shortest_paths_dijkstra()` and `igraph_get_shortest_paths_bellman_ford()` now validate the `from` vertex.
+ - Fixed bugs in `igraph_local_scan_1_ecount()` for weighted undirected graphs which would miscount loops and multi-edges.
### Deprecated
- `igraph_automorphisms()` is now deprecated; its new name is `igraph_count_automorphisms()`. The old name is kept available until at least igraph 0.11.
- `igraph_hub_score()` and `igraph_authority_score()` are now deprecated. Use `igraph_hub_and_authority_scores()` instead.
- `igraph_get_incidence()` is now deprecated; its new name is `igraph_get_biadjacency()` to reflect that the returned matrix is an _adjacency_ matrix between pairs of vertices and not an _incidence_ matrix between vertices and edges. The new name is kept available until at least igraph 0.11. We plan to re-use the name in later versions to provide a proper incidence matrix where the rows are vertices and the columns are edges.
+- `igraph_hrg_dendrogram()` is deprecated because it requires an attribute handler and it goes against the convention of returning attributes in vectors where possible. Use `igraph_from_hrg_dendrogram()` instead, which constructs the dendrogram as an igraph graph _and_ returns the associated probabilities in a vector.
### Other
- Improved performance for `igraph_vertex_connectivity()`.
+ - `igraph_simplify()` makes use of the cache, and avoids simplification when the graph is already known to be simple.
- Documentation improvements.
## [0.10.4] - 2023-01-26
@@ -33,7 +38,7 @@
### Added
- `igraph_get_shortest_path_astar()` finds a shortest path with the A* algorithm.
- - `igraph_vertex_coloring_greedy()` now supports the DSatur heuristics (#2284, thanks to @professorcode1).
+ - `igraph_vertex_coloring_greedy()` now supports the DSatur heuristics through `IGRAPH_COLORING_GREEDY_DSATUR` (#2284, thanks to @professorcode1).
### Changed
diff --git a/src/vendor/cigraph/CMakeLists.txt b/src/vendor/cigraph/CMakeLists.txt
index faef69dcdd1..e84779f9f54 100644
--- a/src/vendor/cigraph/CMakeLists.txt
+++ b/src/vendor/cigraph/CMakeLists.txt
@@ -4,6 +4,7 @@
# * CROSSCOMPILING_EMULATOR can be a semicolon-separated list to pass arguments (3.15)
# * SKIP_REGULAR_EXPRESSION to handle skipped tests properly (3.16)
# * CheckLinkerFlag for HAVE_NEW_DTAGS test (3.18)
+# * cmake -E cat (3.18)
cmake_minimum_required(VERSION 3.18...3.25)
# Add etc/cmake to CMake's search path so we can put our private stuff there
diff --git a/src/vendor/cigraph/azure-pipelines.yml b/src/vendor/cigraph/azure-pipelines.yml
index 15bed1aaf61..165cfe5b05b 100644
--- a/src/vendor/cigraph/azure-pipelines.yml
+++ b/src/vendor/cigraph/azure-pipelines.yml
@@ -76,7 +76,7 @@ jobs:
extra_cmake_args: '-DBLA_VENDOR=OpenBLAS'
build_shared: true
- - job: linux_clang_15
+ - job: linux_clang_17
pool:
vmImage: 'ubuntu-22.04'
steps:
@@ -84,13 +84,13 @@ jobs:
sudo apt-get install ninja-build ccache -y
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
- sudo ./llvm.sh 15
+ sudo ./llvm.sh 17
displayName: Install dependencies
- template: .azure/build.yml
parameters:
build_type: Debug
- extra_cmake_args: '-DUSE_SANITIZER=Address\;Undefined -DCMAKE_C_FLAGS="-Og -fno-sanitize-recover=undefined -fno-sanitize=float-divide-by-zero" -DCMAKE_CXX_FLAGS="-Og -fno-sanitize-recover=undefined -fno-sanitize=float-divide-by-zero" -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15'
+ extra_cmake_args: '-DUSE_SANITIZER=Address\;Undefined -DCMAKE_C_FLAGS="-Og -fno-sanitize-recover=undefined -fno-sanitize=float-divide-by-zero" -DCMAKE_CXX_FLAGS="-Og -fno-sanitize-recover=undefined -fno-sanitize=float-divide-by-zero" -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17'
- job: linux_x87
steps:
diff --git a/src/vendor/cigraph/include/igraph_coloring.h b/src/vendor/cigraph/include/igraph_coloring.h
index ff7f690f081..845cd77d359 100644
--- a/src/vendor/cigraph/include/igraph_coloring.h
+++ b/src/vendor/cigraph/include/igraph_coloring.h
@@ -38,8 +38,9 @@ __BEGIN_DECLS
* \enumval IGRAPH_COLORING_GREEDY_DSATUR
* Choose the vertex with largest number of unique colors in its neighborhood, i.e. its
* "saturation degree". When multiple vertices have the same saturation degree, choose
- * the one with the most not yet colored neighbors. This heuristic is known as "DSatur",
- * and was introduced in Daniel Brélaz: New methods to color the vertices of a graph,
+ * the one with the most not yet colored neighbors. Added in igraph 0.10.4. This heuristic
+ * is known as "DSatur", and was proposed in
+ * Daniel Brélaz: New methods to color the vertices of a graph,
* Commun. ACM 22, 4 (1979), 251–256. https://doi.org/10.1145/359094.359101
*/
typedef enum {
diff --git a/src/vendor/cigraph/include/igraph_error.h b/src/vendor/cigraph/include/igraph_error.h
index f1bea33ac66..d0d6bf37224 100644
--- a/src/vendor/cigraph/include/igraph_error.h
+++ b/src/vendor/cigraph/include/igraph_error.h
@@ -777,8 +777,8 @@ IGRAPH_EXPORT int IGRAPH_FINALLY_STACK_SIZE(void);
*
* \param expr An expression, usually a call to a user-defined callback function.
* It is guaranteed to be evaluated only once.
- * \param code Pointer to an optional variable of type \c igraph_error_t; the
- * value of this variable will be set to the error code if it is not a null
+ * \param code Pointer to an optional variable of type igraph_error_t;
+ * the value of this variable will be set to the error code if it is not a null
* pointer.
*/
#define IGRAPH_CHECK_CALLBACK(expr, code) \
@@ -852,6 +852,7 @@ typedef void igraph_warning_handler_t (const char *reason, const char *file, int
* \brief Installs a warning handler.
*
* Install the supplied warning handler function.
+ *
* \param new_handler The new warning handler function to install.
* Supply a null pointer here to uninstall the current
* warning handler, without installing a new one.
@@ -976,7 +977,7 @@ IGRAPH_EXPORT void igraph_warningf(const char *reason, const char *file, int lin
*
* \param reason Textual description of the error.
* \param file The source file in which the error is noticed.
- * \param line The number of the line in the source file which triggered the error
+ * \param line The number of the line in the source file which triggered the error.
*/
typedef void igraph_fatal_handler_t (const char *reason, const char *file, int line);
@@ -1046,6 +1047,7 @@ IGRAPH_EXPORT IGRAPH_FUNCATTR_NORETURN void igraph_fatalf(const char *reason, co
* \a igraph functions can use this macro when a fatal error occurs and
* want to pass on extra information to the user about what went wrong.
* It calls \ref igraph_fatalf() with the proper parameters.
+ *
* \param reason Textual description of the error, a template string
* with the same syntax as the standard printf C library function.
* \param ... The additional arguments to be substituted into the
diff --git a/src/vendor/cigraph/include/igraph_games.h b/src/vendor/cigraph/include/igraph_games.h
index 1214ad2abd2..e9384fd59ca 100644
--- a/src/vendor/cigraph/include/igraph_games.h
+++ b/src/vendor/cigraph/include/igraph_games.h
@@ -49,9 +49,6 @@ IGRAPH_EXPORT igraph_error_t igraph_barabasi_game(igraph_t *graph, igraph_intege
igraph_bool_t directed,
igraph_barabasi_algorithm_t algo,
const igraph_t *start_from);
-IGRAPH_EXPORT igraph_error_t igraph_erdos_renyi_game(igraph_t *graph, igraph_erdos_renyi_t type,
- igraph_integer_t n, igraph_real_t p_or_m,
- igraph_bool_t directed, igraph_bool_t loops);
IGRAPH_EXPORT igraph_error_t igraph_erdos_renyi_game_gnp(igraph_t *graph, igraph_integer_t n, igraph_real_t p,
igraph_bool_t directed, igraph_bool_t loops);
IGRAPH_EXPORT igraph_error_t igraph_erdos_renyi_game_gnm(igraph_t *graph, igraph_integer_t n, igraph_integer_t m,
@@ -220,6 +217,13 @@ IGRAPH_EXPORT igraph_error_t igraph_sample_sphere_volume(igraph_integer_t dim, i
IGRAPH_EXPORT igraph_error_t igraph_sample_dirichlet(igraph_integer_t n, const igraph_vector_t *alpha,
igraph_matrix_t *res);
+/* Deprecated functions: */
+
+IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_erdos_renyi_game(
+ igraph_t *graph, igraph_erdos_renyi_t type, igraph_integer_t n,
+ igraph_real_t p_or_m, igraph_bool_t directed, igraph_bool_t loops
+);
+
__END_DECLS
#endif
diff --git a/src/vendor/cigraph/include/igraph_hrg.h b/src/vendor/cigraph/include/igraph_hrg.h
index 40b699c4c8d..6ceeb4cac24 100644
--- a/src/vendor/cigraph/include/igraph_hrg.h
+++ b/src/vendor/cigraph/include/igraph_hrg.h
@@ -98,8 +98,9 @@ IGRAPH_EXPORT igraph_error_t igraph_hrg_game(
igraph_t *graph, const igraph_hrg_t *hrg
);
-IGRAPH_EXPORT igraph_error_t igraph_hrg_dendrogram(igraph_t *graph,
- const igraph_hrg_t *hrg);
+IGRAPH_EXPORT igraph_error_t igraph_from_hrg_dendrogram(
+ igraph_t *graph, const igraph_hrg_t *hrg, igraph_vector_t *prob
+);
IGRAPH_EXPORT igraph_error_t igraph_hrg_consensus(const igraph_t *graph,
igraph_vector_int_t *parents,
@@ -120,6 +121,12 @@ IGRAPH_EXPORT igraph_error_t igraph_hrg_create(igraph_hrg_t *hrg,
const igraph_t *graph,
const igraph_vector_t *prob);
+/* Deprecated functions: */
+
+IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_hrg_dendrogram(
+ igraph_t *graph, const igraph_hrg_t *hrg
+);
+
__END_DECLS
#endif /* IGRAPH_HRG_H */
diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml
index 53af2c2e904..5110b77175c 100644
--- a/src/vendor/cigraph/interfaces/functions.yaml
+++ b/src/vendor/cigraph/interfaces/functions.yaml
@@ -224,11 +224,6 @@ igraph_barabasi_game:
BOOLEAN directed=True, BARABASI_ALGORITHM algo=BAG,
OPTIONAL GRAPH start_from
-igraph_erdos_renyi_game:
- PARAMS: |-
- OUT GRAPH graph, ERDOS_RENYI_TYPE type, INTEGER n, REAL p_or_m,
- BOOLEAN directed=False, BOOLEAN loops=False
-
igraph_erdos_renyi_game_gnp:
PARAMS: OUT GRAPH graph, INTEGER n, REAL p, BOOLEAN directed=False, BOOLEAN loops=False
@@ -1711,9 +1706,6 @@ igraph_hrg_sample_many:
igraph_hrg_game:
PARAMS: OUT GRAPH graph, HRG hrg
-igraph_hrg_dendrogram:
- PARAMS: OUT GRAPH graph, HRG hrg
-
igraph_hrg_consensus:
PARAMS: |-
GRAPH graph, OUT VECTOR_INT parents, OUT VECTOR weights,
@@ -1738,6 +1730,9 @@ igraph_hrg_size:
PARAMS: HRG hrg
RETURN: INTEGER
+igraph_from_hrg_dendrogram:
+ PARAMS: OUT GRAPH graph, HRG hrg, OUT VECTOR prob
+
#######################################
# Conversion
#######################################
diff --git a/src/vendor/cigraph/src/CMakeLists.txt b/src/vendor/cigraph/src/CMakeLists.txt
index 261f2b95111..fca49d6e5d9 100644
--- a/src/vendor/cigraph/src/CMakeLists.txt
+++ b/src/vendor/cigraph/src/CMakeLists.txt
@@ -373,31 +373,31 @@ if(MATH_LIBRARY)
endif()
if(ARPACK_LIBRARIES)
- target_link_libraries(igraph PUBLIC ${ARPACK_LIBRARIES})
+ target_link_libraries(igraph PRIVATE ${ARPACK_LIBRARIES})
endif()
-if(BLAS_LIBRARIES)
- target_link_libraries(igraph PUBLIC ${BLAS_LIBRARIES})
+if(BLAS_FOUND)
+ target_link_libraries(igraph PRIVATE ${BLAS_LIBRARIES})
endif()
if(GLPK_LIBRARIES)
- target_link_libraries(igraph PUBLIC ${GLPK_LIBRARIES})
+ target_link_libraries(igraph PRIVATE ${GLPK_LIBRARIES})
endif()
if(GMP_LIBRARIES)
- target_link_libraries(igraph PUBLIC ${GMP_LIBRARIES})
+ target_link_libraries(igraph PRIVATE ${GMP_LIBRARIES})
endif()
if(LAPACK_LIBRARIES)
- target_link_libraries(igraph PUBLIC ${LAPACK_LIBRARIES})
+ target_link_libraries(igraph PRIVATE ${LAPACK_LIBRARIES})
endif()
if(LIBXML2_LIBRARIES)
- target_link_libraries(igraph PUBLIC ${LIBXML2_LIBRARIES})
+ target_link_libraries(igraph PRIVATE ${LIBXML2_LIBRARIES})
endif()
if(PLFIT_LIBRARIES)
- target_link_libraries(igraph PUBLIC ${PLFIT_LIBRARIES})
+ target_link_libraries(igraph PRIVATE ${PLFIT_LIBRARIES})
endif()
# Link igraph statically to some of the libraries from the subdirectories
diff --git a/src/vendor/cigraph/src/community/leading_eigenvector.c b/src/vendor/cigraph/src/community/leading_eigenvector.c
index 264d0227775..19863746cc7 100644
--- a/src/vendor/cigraph/src/community/leading_eigenvector.c
+++ b/src/vendor/cigraph/src/community/leading_eigenvector.c
@@ -410,14 +410,11 @@ igraph_error_t igraph_community_leading_eigenvector(
igraph_vector_list_clear(eigenvectors);
}
- IGRAPH_STATUS("Starting leading eigenvector method.\n", 0);
-
if (!start) {
/* Calculate the weakly connected components in the graph and use them as
* an initial split */
IGRAPH_CHECK(igraph_connected_components(graph, mymembership, &idx, 0, IGRAPH_WEAK));
communities = igraph_vector_int_size(&idx);
- IGRAPH_STATUSF(("Starting from %" IGRAPH_PRId " component(s).\n", 0, communities));
if (history) {
IGRAPH_CHECK(igraph_vector_push_back(history,
IGRAPH_LEVC_HIST_START_FULL));
@@ -425,8 +422,6 @@ igraph_error_t igraph_community_leading_eigenvector(
} else {
/* Just create the idx vector for the given membership vector */
communities = igraph_vector_int_max(mymembership) + 1;
- IGRAPH_STATUSF(("Starting from given membership vector with %" IGRAPH_PRId
- " communities.\n", 0, communities));
if (history) {
IGRAPH_CHECK(igraph_vector_push_back(history,
IGRAPH_LEVC_HIST_START_GIVEN));
@@ -512,7 +507,6 @@ igraph_error_t igraph_community_leading_eigenvector(
/* depth first search */
igraph_integer_t size = 0;
- IGRAPH_STATUSF(("Trying to split community %" IGRAPH_PRId "... ", 0, comm));
IGRAPH_ALLOW_INTERRUPTION();
for (i = 0; i < no_of_nodes; i++) {
@@ -631,7 +625,6 @@ igraph_error_t igraph_community_leading_eigenvector(
}
if (storage.d[0] <= 0) {
- IGRAPH_STATUS("no split.\n", 0);
if (history) {
IGRAPH_CHECK(igraph_vector_push_back(history,
IGRAPH_LEVC_HIST_FAILED));
@@ -651,7 +644,6 @@ igraph_error_t igraph_community_leading_eigenvector(
}
}
if (l == 0 || l == size) {
- IGRAPH_STATUS("no split.\n", 0);
if (history) {
IGRAPH_CHECK(igraph_vector_push_back(history,
IGRAPH_LEVC_HIST_FAILED));
@@ -667,7 +659,6 @@ igraph_error_t igraph_community_leading_eigenvector(
mod += storage.v[size + i] * storage.v[i];
}
if (mod <= 1e-8) {
- IGRAPH_STATUS("no modularity increase, no split.\n", 0);
if (history) {
IGRAPH_CHECK(igraph_vector_push_back(history,
IGRAPH_LEVC_HIST_FAILED));
@@ -677,7 +668,6 @@ igraph_error_t igraph_community_leading_eigenvector(
}
communities++;
- IGRAPH_STATUS("split.\n", 0);
/* Rewrite the mymembership vector */
for (j = 0; j < size; j++) {
@@ -720,8 +710,6 @@ igraph_error_t igraph_community_leading_eigenvector(
igraph_vector_int_destroy(&idx2);
IGRAPH_FINALLY_CLEAN(3);
- IGRAPH_STATUS("Done.\n", 0);
-
/* reform the mymerges vector */
if (merges) {
igraph_vector_int_null(&idx);
diff --git a/src/vendor/cigraph/src/community/louvain.c b/src/vendor/cigraph/src/community/louvain.c
index 5a3d823340a..a6a84c56ef8 100644
--- a/src/vendor/cigraph/src/community/louvain.c
+++ b/src/vendor/cigraph/src/community/louvain.c
@@ -414,7 +414,7 @@ static igraph_error_t igraph_i_community_multilevel_step(
new_id = old_id;
/* Update old community */
- igraph_vector_int_set(communities.membership, ni, -1);
+ VECTOR(*communities.membership)[ni] = -1;
communities.item[old_id].size--;
if (communities.item[old_id].size == 0) {
communities.communities_no--;
@@ -447,7 +447,7 @@ static igraph_error_t igraph_i_community_multilevel_step(
/* debug("Added vertex %ld to community %ld (gain %lf).\n", ni, new_id, (double) max_q_gain); */
/* Add vertex to "new" community and update it */
- igraph_vector_int_set(communities.membership, ni, new_id);
+ VECTOR(*communities.membership)[ni] = new_id;
if (communities.item[new_id].size == 0) {
communities.communities_no++;
}
diff --git a/src/vendor/cigraph/src/community/modularity.c b/src/vendor/cigraph/src/community/modularity.c
index 9dd0949c0fe..57a855dd7f8 100644
--- a/src/vendor/cigraph/src/community/modularity.c
+++ b/src/vendor/cigraph/src/community/modularity.c
@@ -97,7 +97,7 @@
* It does not have to be consecutive, i.e. empty communities
* are allowed.
* \param weights Weight vector or \c NULL if no weights are specified.
- * \param resolution The resolutin parameter \c γ. Must not be negative.
+ * \param resolution The resolution parameter \c γ. Must not be negative.
* Set it to 1 to use the classical definition of modularity.
* \param directed Whether to use the directed or undirected version of modularity.
* Ignored for undirected graphs.
diff --git a/src/vendor/cigraph/src/community/walktrap/walktrap_graph.cpp b/src/vendor/cigraph/src/community/walktrap/walktrap_graph.cpp
index 39830be363a..5cb63bca5a4 100644
--- a/src/vendor/cigraph/src/community/walktrap/walktrap_graph.cpp
+++ b/src/vendor/cigraph/src/community/walktrap/walktrap_graph.cpp
@@ -200,7 +200,7 @@ igraph_error_t Graph::convert_from_igraph(const igraph_t *graph,
* See https://github.com/igraph/igraph/pull/2043 */
if (G.vertices[i].total_weight == 0) {
/* G.vertices will be destroyed by Graph::~Graph() */
- IGRAPH_ERROR("Vertex with zero strength found: all vertices must have positive strength for walktrap",
+ IGRAPH_ERROR("Vertex with zero strength found: all vertices must have positive strength for walktrap.",
IGRAPH_EINVAL);
}
sort(G.vertices[i].edges, G.vertices[i].edges + G.vertices[i].degree);
diff --git a/src/vendor/cigraph/src/connectivity/cohesive_blocks.c b/src/vendor/cigraph/src/connectivity/cohesive_blocks.c
index dadc73e85c2..955a0a9e0ca 100644
--- a/src/vendor/cigraph/src/connectivity/cohesive_blocks.c
+++ b/src/vendor/cigraph/src/connectivity/cohesive_blocks.c
@@ -249,8 +249,6 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph,
IGRAPH_EINVAL);
}
- IGRAPH_STATUS("Starting cohesive block calculation.\n", NULL);
-
if (blocks) {
igraph_vector_int_list_clear(blocks);
}
@@ -304,16 +302,12 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph,
igraph_integer_t nsepv = 0;
igraph_bool_t addedsep = false;
- IGRAPH_STATUSF(("Candidate %li: %li vertices,",
- 0, Qptr, mynodes));
IGRAPH_ALLOW_INTERRUPTION();
/* Get the separators */
IGRAPH_CHECK(igraph_minimum_size_separators(mygraph, &separators));
nsep = igraph_vector_int_list_size(&separators);
- IGRAPH_STATUSF((" %li separators,", 0, nsep));
-
/* Remove them from the graph, also mark them */
IGRAPH_CHECK(igraph_vector_bool_resize(&marked, mynodes));
igraph_vector_bool_null(&marked);
@@ -350,8 +344,6 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph,
no++;
}
- IGRAPH_STATUSF((" %li new candidates,", 0, no));
-
for (i = 0; i < no; i++) {
igraph_t *newgraph;
igraph_integer_t maxdeg;
@@ -398,8 +390,6 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph,
}
}
- IGRAPH_STATUSF((" keeping %li.\n", 0, kept));
-
igraph_destroy(mygraph);
igraph_free(mygraph);
VECTOR(Q)[Qptr] = NULL;
@@ -499,10 +489,7 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph,
for (i = 0; i < Qptr; i++) {
if (VECTOR(removed)[i]) {
- IGRAPH_STATUSF(("Candidate %li ignored.\n", 0, i));
continue;
- } else {
- IGRAPH_STATUSF(("Candidate %li is a cohesive (sub)block\n", 0, i));
}
VECTOR(rewritemap)[i] = resptr;
if (cohesion) {
@@ -576,7 +563,5 @@ igraph_error_t igraph_cohesive_blocks(const igraph_t *graph,
igraph_vector_ptr_destroy(&Q);
IGRAPH_FINALLY_CLEAN(2); /* + the elements of Q, they were already destroyed */
- IGRAPH_STATUS("Cohesive blocking done.\n", 0);
-
return IGRAPH_SUCCESS;
}
diff --git a/src/vendor/cigraph/src/connectivity/separators.c b/src/vendor/cigraph/src/connectivity/separators.c
index b9970df13ea..3f3a958a12e 100644
--- a/src/vendor/cigraph/src/connectivity/separators.c
+++ b/src/vendor/cigraph/src/connectivity/separators.c
@@ -118,7 +118,7 @@ static igraph_error_t igraph_i_is_separator(const igraph_t *graph,
}
}
- /* Look for the next node that was neighter removed, not visited */
+ /* Look for the next node that was neither removed, not visited */
while (start < no_of_nodes && VECTOR(*removed)[start]) {
start++;
}
@@ -559,6 +559,7 @@ static igraph_error_t igraph_i_minimum_size_separators_append(
igraph_integer_t j;
while (!igraph_vector_int_list_empty(new)) {
+ igraph_vector_int_t *oldvec;
igraph_vector_int_t *newvec = igraph_vector_int_list_tail_ptr(new);
/* Check whether the separator is already in `old' */
@@ -570,10 +571,11 @@ static igraph_error_t igraph_i_minimum_size_separators_append(
}
if (j == olen) {
- /* We have found a new separator, append it to `old' */
- /* TODO: we should have a more efficient method for moving a vector
- * from one vector_list to another */
- IGRAPH_CHECK(igraph_vector_int_list_push_back_copy(old, newvec));
+ /* We have found a new separator, append it to `old'. We do it by
+ * extending it with an empty vector and then swapping it with
+ * the new vector to be appended */
+ IGRAPH_CHECK(igraph_vector_int_list_push_back_new(old, &oldvec));
+ igraph_vector_int_swap(oldvec, newvec);
olen++;
}
diff --git a/src/vendor/cigraph/src/core/genheap.c b/src/vendor/cigraph/src/core/genheap.c
index 0f251e8fd64..1e4ec3f3fa9 100644
--- a/src/vendor/cigraph/src/core/genheap.c
+++ b/src/vendor/cigraph/src/core/genheap.c
@@ -111,13 +111,18 @@ igraph_error_t igraph_gen2wheap_init(
int (*cmp)(const void *, const void *),
size_t item_size, igraph_integer_t max_size
) {
+ /* TODO: Currently, storage is allocated for the maximum number of elements
+ * right from the start. This is sufficient for the only use case as of this
+ * writing, the D-SATUR graph colouring algorithm, but it may not be efficcient
+ * for other use cases. Consider improving this in the future.
+ */
h->max_size = max_size;
/* We start with the biggest */
IGRAPH_VECTOR_INT_INIT_FINALLY(&h->index2, max_size);
h->cmp = cmp;
h->item_size = item_size;
h->data = igraph_calloc(max_size, item_size);
- IGRAPH_CHECK_OOM(h->data, "Cannot initialized generic heap.");
+ IGRAPH_CHECK_OOM(h->data, "Cannot initialize generic heap.");
IGRAPH_FINALLY(igraph_free, h->data);
IGRAPH_CHECK(igraph_vector_int_init(&h->index, 0));
diff --git a/src/vendor/cigraph/src/core/grid.c b/src/vendor/cigraph/src/core/grid.c
index f5ffe869dc3..810f5d7b3c8 100644
--- a/src/vendor/cigraph/src/core/grid.c
+++ b/src/vendor/cigraph/src/core/grid.c
@@ -195,87 +195,14 @@ igraph_bool_t igraph_2dgrid_in(const igraph_2dgrid_t *grid, igraph_integer_t ele
return VECTOR(grid->next)[elem] != -1;
}
-igraph_real_t igraph_2dgrid_dist(const igraph_2dgrid_t *grid,
- igraph_integer_t e1, igraph_integer_t e2) {
- igraph_real_t x = MATRIX(*grid->coords, e1, 0) - MATRIX(*grid->coords, e2, 0);
- igraph_real_t y = MATRIX(*grid->coords, e1, 1) - MATRIX(*grid->coords, e2, 1);
-
- return sqrt(x*x + y*y);
-}
-
-igraph_real_t igraph_2dgrid_dist2(const igraph_2dgrid_t *grid,
- igraph_integer_t e1, igraph_integer_t e2) {
+igraph_real_t igraph_2dgrid_sq_dist(const igraph_2dgrid_t *grid,
+ igraph_integer_t e1, igraph_integer_t e2) {
igraph_real_t x = MATRIX(*grid->coords, e1, 0) - MATRIX(*grid->coords, e2, 0);
igraph_real_t y = MATRIX(*grid->coords, e1, 1) - MATRIX(*grid->coords, e2, 1);
return x * x + y * y;
}
-static igraph_error_t igraph_i_2dgrid_addvertices(igraph_2dgrid_t *grid, igraph_vector_int_t *eids,
- igraph_integer_t vid, igraph_real_t r,
- igraph_integer_t x, igraph_integer_t y) {
- igraph_integer_t act;
- igraph_integer_t *v = VECTOR(grid->next);
-
- r = r * r;
- act = MATRIX(grid->startidx, x, y);
- while (act != 0) {
- if (igraph_2dgrid_dist2(grid, vid, act - 1) < r) {
- IGRAPH_CHECK(igraph_vector_int_push_back(eids, act - 1));
- }
- act = v[act - 1];
- }
- return IGRAPH_SUCCESS;
-}
-
-igraph_error_t igraph_2dgrid_neighbors(igraph_2dgrid_t *grid, igraph_vector_int_t *eids,
- igraph_integer_t vid, igraph_real_t r) {
- igraph_real_t xc = MATRIX(*grid->coords, vid, 0);
- igraph_real_t yc = MATRIX(*grid->coords, vid, 1);
- igraph_integer_t x, y;
- igraph_vector_int_clear(eids);
-
- igraph_i_2dgrid_which(grid, xc, yc, &x, &y);
-
- /* this cell */
- IGRAPH_CHECK(igraph_i_2dgrid_addvertices(grid, eids, vid, r, x, y));
-
- /* left */
- if (x != 0) {
- IGRAPH_CHECK(igraph_i_2dgrid_addvertices(grid, eids, vid, r, x - 1, y));
- }
- /* right */
- if (x != grid->stepsx - 1) {
- IGRAPH_CHECK(igraph_i_2dgrid_addvertices(grid, eids, vid, r, x + 1, y));
- }
- /* up */
- if (y != 0) {
- IGRAPH_CHECK(igraph_i_2dgrid_addvertices(grid, eids, vid, r, x, y - 1));
- }
- /* down */
- if (y != grid->stepsy - 1) {
- IGRAPH_CHECK(igraph_i_2dgrid_addvertices(grid, eids, vid, r, x, y + 1));
- }
- /* up & left */
- if (x != 0 && y != 0) {
- IGRAPH_CHECK(igraph_i_2dgrid_addvertices(grid, eids, vid, r, x - 1, y - 1));
- }
- /* up & right */
- if (x != grid->stepsx - 1 && y != 0) {
- IGRAPH_CHECK(igraph_i_2dgrid_addvertices(grid, eids, vid, r, x + 1, y - 1));
- }
- /* down & left */
- if (x != 0 && y != grid->stepsy - 1) {
- IGRAPH_CHECK(igraph_i_2dgrid_addvertices(grid, eids, vid, r, x - 1, y + 1));
- }
- /* down & right */
- if (x != grid->stepsx - 1 && y != grid->stepsy - 1) {
- IGRAPH_CHECK(igraph_i_2dgrid_addvertices(grid, eids, vid, r, x - 1, y + 1));
- }
-
- return IGRAPH_SUCCESS;
-}
-
void igraph_2dgrid_reset(igraph_2dgrid_t *grid, igraph_2dgrid_iterator_t *it) {
/* Search for the first cell containing a vertex */
it->x = 0; it->y = 0; it->vid = MATRIX(grid->startidx, 0, 0);
diff --git a/src/vendor/cigraph/src/core/grid.h b/src/vendor/cigraph/src/core/grid.h
index d7496c9708b..26d7a67e8f2 100644
--- a/src/vendor/cigraph/src/core/grid.h
+++ b/src/vendor/cigraph/src/core/grid.h
@@ -58,10 +58,6 @@ void igraph_2dgrid_move(igraph_2dgrid_t *grid, igraph_integer_t elem,
void igraph_2dgrid_getcenter(const igraph_2dgrid_t *grid,
igraph_real_t *massx, igraph_real_t *massy);
igraph_bool_t igraph_2dgrid_in(const igraph_2dgrid_t *grid, igraph_integer_t elem);
-igraph_real_t igraph_2dgrid_dist(const igraph_2dgrid_t *grid,
- igraph_integer_t e1, igraph_integer_t e2);
-igraph_error_t igraph_2dgrid_neighbors(igraph_2dgrid_t *grid, igraph_vector_int_t *eids,
- igraph_integer_t vid, igraph_real_t r);
typedef struct igraph_2dgrid_iterator_t {
igraph_integer_t vid, x, y;
diff --git a/src/vendor/cigraph/src/core/sparsemat.c b/src/vendor/cigraph/src/core/sparsemat.c
index ddee4f14d5a..b73455eaa56 100644
--- a/src/vendor/cigraph/src/core/sparsemat.c
+++ b/src/vendor/cigraph/src/core/sparsemat.c
@@ -771,6 +771,7 @@ igraph_error_t igraph_sparsemat_is_symmetric(const igraph_sparsemat_t *A, igraph
* single matrix entry in multiple pieces. The entry is then the sum
* of all its pieces. (Some functions create matrices like this.) This
* function eliminates the multiple pieces.
+ *
* \param A The input matrix, in column-compressed format.
* \return Error code.
*
@@ -806,6 +807,7 @@ static CS_INT fkeep_wrapper(CS_INT row, CS_INT col, double value, void* data) {
* sparse matrix. For all entries, it calls the supplied function and
* depending on the return values either keeps, or deleted the element
* from the matrix.
+ *
* \param A The input matrix, in column-compressed format.
* \param fkeep The filter function. It must take four arguments: the
* first is an \c igraph_integer_t, the row index of the entry, the second is
@@ -849,6 +851,7 @@ igraph_error_t igraph_sparsemat_fkeep(
*
* As a result of matrix operations, some of the entries in a sparse
* matrix might be zero. This function removes these entries.
+ *
* \param A The input matrix, it must be in column-compressed format.
* \return Error code.
*
@@ -871,6 +874,7 @@ igraph_error_t igraph_sparsemat_dropzeros(igraph_sparsemat_t *A) {
* This function is similar to \ref igraph_sparsemat_dropzeros(), but it
* also drops entries that are closer to zero than the given tolerance
* threshold.
+ *
* \param A The input matrix, it must be in column-compressed format.
* \param tol Real number, giving the tolerance threshold.
* \return Error code.
@@ -896,6 +900,7 @@ igraph_error_t igraph_sparsemat_droptol(igraph_sparsemat_t *A, igraph_real_t tol
* \brief Matrix multiplication.
*
* Multiplies two sparse matrices.
+ *
* \param A The first input matrix (left hand side), in
* column-compressed format.
* \param B The second input matrix (right hand side), in
@@ -988,6 +993,7 @@ igraph_error_t igraph_sparsemat_gaxpy(const igraph_sparsemat_t *A,
*
* Solve the Lx=b linear equation system, where the L coefficient
* matrix is square and lower-triangular, with a zero-free diagonal.
+ *
* \param L The input matrix, in column-compressed format.
* \param b The right hand side of the linear system.
* \param res An initialized vector, the result is stored here.
@@ -1021,6 +1027,7 @@ igraph_error_t igraph_sparsemat_lsolve(const igraph_sparsemat_t *L,
*
* Solve the L'x=b linear equation system, where the L
* matrix is square and lower-triangular, with a zero-free diagonal.
+ *
* \param L The input matrix, in column-compressed format.
* \param b The right hand side of the linear system.
* \param res An initialized vector, the result is stored here.
@@ -1054,6 +1061,7 @@ igraph_error_t igraph_sparsemat_ltsolve(const igraph_sparsemat_t *L,
* \brief Solves an upper-triangular linear system.
*
* Solves the Ux=b upper triangular system.
+ *
* \param U The input matrix, in column-compressed format.
* \param b The right hand side of the linear system.
* \param res An initialized vector, the result is stored here.
@@ -1087,6 +1095,7 @@ igraph_error_t igraph_sparsemat_usolve(const igraph_sparsemat_t *U,
*
* This is the same as \ref igraph_sparsemat_usolve(), but U'x=b is
* solved, where the apostrophe denotes the transpose.
+ *
* \param U The input matrix, in column-compressed format.
* \param b The right hand side of the linear system.
* \param res An initialized vector, the result is stored here.
@@ -1121,6 +1130,7 @@ igraph_error_t igraph_sparsemat_utsolve(const igraph_sparsemat_t *U,
* \brief Solves a symmetric linear system via Cholesky decomposition.
*
* Solve Ax=b, where A is a symmetric positive definite matrix.
+ *
* \param A The input matrix, in column-compressed format.
* \param v The right hand side.
* \param res An initialized vector, the result is stored here.
@@ -1158,6 +1168,7 @@ igraph_error_t igraph_sparsemat_cholsol(const igraph_sparsemat_t *A,
* \brief Solves a linear system via LU decomposition.
*
* Solve Ax=b, via LU factorization of A.
+ *
* \param A The input matrix, in column-compressed format.
* \param b The right hand side of the equation.
* \param res An initialized vector, the result is stored here.
@@ -1273,6 +1284,7 @@ static igraph_error_t igraph_i_sparsemat_triplet(igraph_t *graph, const igraph_s
* then delete the entries in the upper diagonal first, or call \ref
* igraph_simplify() on the result graph to eliminate the multiple
* edges.
+ *
* \param graph Pointer to an uninitialized igraph_t object, the
* graphs is stored here.
* \param A The input matrix, in triplet or column-compressed format.
@@ -1409,6 +1421,7 @@ igraph_error_t igraph_weighted_sparsemat(igraph_t *graph, const igraph_sparsemat
* Only the non-zero entries are printed. This function serves more as
* a debugging utility, as currently there is no function that could
* read back the printed matrix from the file.
+ *
* \param A The input matrix, triplet or column-compressed format.
* \param outstream The stream to print it to.
* \return Error code.
@@ -1762,6 +1775,7 @@ igraph_error_t igraph_sparsemat_arpack_rssolve(const igraph_sparsemat_t *A,
* \brief Eigenvalues and eigenvectors of a nonsymmetric sparse matrix via ARPACK.
*
* Eigenvalues and/or eigenvectors of a nonsymmetric sparse matrix.
+ *
* \param A The input matrix, in column-compressed mode.
* \param options ARPACK options, it is passed to \ref
* igraph_arpack_rnsolve(). Supply \c NULL here to use the defaults.
@@ -1815,6 +1829,7 @@ igraph_error_t igraph_sparsemat_arpack_rnsolve(const igraph_sparsemat_t *A,
* QR decomposition of sparse matrices involves two steps, the first
* is calling this function, and then \ref
* igraph_sparsemat_qr().
+ *
* \param order The ordering to use: 0 means natural ordering, 1 means
* minimum degree ordering of A+A', 2 is minimum degree ordering of
* A'A after removing the dense rows from A, and 3 is the minimum
@@ -1845,6 +1860,7 @@ igraph_error_t igraph_sparsemat_symbqr(igraph_integer_t order, const igraph_spar
*
* LU decomposition of sparse matrices involves two steps, the first
* is calling this function, and then \ref igraph_sparsemat_lu().
+ *
* \param order The ordering to use: 0 means natural ordering, 1 means
* minimum degree ordering of A+A', 2 is minimum degree ordering of
* A'A after removing the dense rows from A, and 3 is the minimum
@@ -1874,6 +1890,7 @@ igraph_error_t igraph_sparsemat_symblu(igraph_integer_t order, const igraph_spar
* \brief LU decomposition of a sparse matrix.
*
* Performs numeric sparse LU decomposition of a matrix.
+ *
* \param A The input matrix, in column-compressed format.
* \param dis The symbolic analysis for LU decomposition, coming from
* a call to the \ref igraph_sparsemat_symblu() function.
@@ -1903,6 +1920,7 @@ igraph_error_t igraph_sparsemat_lu(const igraph_sparsemat_t *A,
* \brief QR decomposition of a sparse matrix.
*
* Numeric QR decomposition of a sparse matrix.
+ *
* \param A The input matrix, in column-compressed format.
* \param dis The result of the symbolic QR analysis, from the
* function \ref igraph_sparsemat_symbqr().
@@ -1932,6 +1950,7 @@ igraph_error_t igraph_sparsemat_qr(const igraph_sparsemat_t *A,
* \brief Solves a linear system using a precomputed LU decomposition.
*
* Uses the LU decomposition of a matrix to solve linear systems.
+ *
* \param dis The symbolic analysis of the coefficient matrix, the
* result of \ref igraph_sparsemat_symblu().
* \param din The LU decomposition, the result of a call to \ref
@@ -1987,6 +2006,7 @@ igraph_error_t igraph_sparsemat_luresol(const igraph_sparsemat_symbolic_t *dis,
*
* Solves a linear system using a QR decomposition of its coefficient
* matrix.
+ *
* \param dis Symbolic analysis of the coefficient matrix, the result
* of \ref igraph_sparsemat_symbqr().
* \param din The QR decomposition of the coefficient matrix, the
@@ -2046,6 +2066,7 @@ igraph_error_t igraph_sparsemat_qrresol(const igraph_sparsemat_symbolic_t *dis,
*
* Frees the memory allocated by \ref igraph_sparsemat_symbqr() or
* \ref igraph_sparsemat_symblu().
+ *
* \param dis The symbolic analysis.
*
* Time complexity: O(1).
@@ -2062,6 +2083,7 @@ void igraph_sparsemat_symbolic_destroy(igraph_sparsemat_symbolic_t *dis) {
*
* Frees the memoty allocated by \ref igraph_sparsemat_qr() or \ref
* igraph_sparsemat_lu().
+ *
* \param din The LU or QR decomposition.
*
* Time complexity: O(1).
diff --git a/src/vendor/cigraph/src/flow/flow_conversion.c b/src/vendor/cigraph/src/flow/flow_conversion.c
index bebd3fc0040..01b20a5dddd 100644
--- a/src/vendor/cigraph/src/flow/flow_conversion.c
+++ b/src/vendor/cigraph/src/flow/flow_conversion.c
@@ -56,8 +56,8 @@
* halves of the vertices and the remaining \em n vertices will correspond to
* the \em input halves, in the same order as in the original graph.
*
- * @param graph the input graph
- * @param result an uninitialized graph object; the result will be returned here
+ * \param graph the input graph
+ * \param result an uninitialized graph object; the result will be returned here
*/
igraph_error_t igraph_i_split_vertices(const igraph_t* graph, igraph_t* result) {
igraph_integer_t no_of_nodes = igraph_vcount(graph);
diff --git a/src/vendor/cigraph/src/games/correlated.c b/src/vendor/cigraph/src/games/correlated.c
index 36a90184315..20f0c95ad3e 100644
--- a/src/vendor/cigraph/src/games/correlated.c
+++ b/src/vendor/cigraph/src/games/correlated.c
@@ -132,9 +132,7 @@ igraph_error_t igraph_correlated_game(const igraph_t *old_graph, igraph_t *new_g
/* Special cases */
if (corr == 0) {
- return igraph_erdos_renyi_game(new_graph, IGRAPH_ERDOS_RENYI_GNP,
- no_of_nodes, p, directed,
- IGRAPH_NO_LOOPS);
+ return igraph_erdos_renyi_game_gnp(new_graph, no_of_nodes, p, directed, IGRAPH_NO_LOOPS);
}
if (corr == 1) {
/* We don't copy, because we don't need the attributes.... */
@@ -320,8 +318,7 @@ igraph_error_t igraph_correlated_pair_game(igraph_t *graph1, igraph_t *graph2,
igraph_bool_t directed,
const igraph_vector_int_t *permutation) {
- IGRAPH_CHECK(igraph_erdos_renyi_game(graph1, IGRAPH_ERDOS_RENYI_GNP, n, p,
- directed, IGRAPH_NO_LOOPS));
+ IGRAPH_CHECK(igraph_erdos_renyi_game_gnp(graph1, n, p, directed, IGRAPH_NO_LOOPS));
IGRAPH_CHECK(igraph_correlated_game(graph1, graph2, corr, p, permutation));
return IGRAPH_SUCCESS;
}
diff --git a/src/vendor/cigraph/src/games/degree_sequence.c b/src/vendor/cigraph/src/games/degree_sequence.c
index cb5bae49cef..6ccf8b1f648 100644
--- a/src/vendor/cigraph/src/games/degree_sequence.c
+++ b/src/vendor/cigraph/src/games/degree_sequence.c
@@ -748,8 +748,8 @@ igraph_error_t igraph_i_degree_sequence_game_edge_switching(
* for \c IGRAPH_DEGSEQ_SIMPLE. The time complexity of the
* other modes is not known.
*
- * \sa \ref igraph_barabasi_game(), \ref igraph_erdos_renyi_game(),
- * \ref igraph_is_graphical()
+ * \sa \ref igraph_barabasi_game(), \ref igraph_erdos_renyi_game_gnm(),
+ * \ref igraph_erdos_renyi_game_gnp(), \ref igraph_is_graphical()
*
* \example examples/simple/igraph_degree_sequence_game.c
*/
diff --git a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.cpp b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.cpp
index 60f3ded632e..586d944fc4c 100644
--- a/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.cpp
+++ b/src/vendor/cigraph/src/games/degree_sequence_vl/gengraph_graph_molloy_hash.cpp
@@ -26,7 +26,6 @@
#include "igraph_constructors.h"
#include "igraph_error.h"
-#include "igraph_statusbar.h"
#include "igraph_progress.h"
#include
@@ -401,20 +400,6 @@ igraph_integer_t graph_molloy_hash::shuffle(igraph_integer_t times,
IGRAPH_WARNING("Cannot shuffle graph, maybe it is the only realization of its degree sequence?");
}
- // Status report
- {
- igraph_status("*** Shuffle Monitor ***\n", NULL);
- igraph_statusf(" - Average cost : %f / validated edge swap\n", NULL,
- double(cost) / double(nb_swaps));
- igraph_statusf(" - Connectivity tests : %" IGRAPH_PRId " (%" IGRAPH_PRId " successes, %" IGRAPH_PRId " failures)\n",
- NULL, successes + failures, successes, failures);
- // %.f rounds to integer
- igraph_statusf(" - Average window : %.f\n", NULL,
- avg_T / double(successes + failures));
- if (type == FINAL_HEURISTICS || type == BRUTE_FORCE_HEURISTICS)
- igraph_statusf(" - Average isolation test width : %f\n", NULL,
- avg_K / double(successes + failures));
- }
return nb_swaps;
}
@@ -561,16 +546,11 @@ igraph_integer_t graph_molloy_hash::optimal_window() {
min_cost = c;
optimal_T = Tmax;
}
- igraph_statusf("Tmax = %" IGRAPH_PRId " [%f]", 0, Tmax, min_cost);
}
- // on cree Tmin
- igraph_integer_t Tmin = igraph_integer_t(0.5 * double(a) / (min_cost - 1.0));
- igraph_statusf("Optimal T is in [%" IGRAPH_PRId ", %" IGRAPH_PRId "]\n", 0, Tmin, Tmax);
// on cherche autour
double span = 2.0;
int try_again = 4;
while (span > 1.05 && optimal_T <= 5 * a) {
- igraph_statusf("Best T [cost]: %" IGRAPH_PRId " [%f]", 0, optimal_T, min_cost);
igraph_integer_t T_low = igraph_integer_t(double(optimal_T) / span);
igraph_integer_t T_high = igraph_integer_t(double(optimal_T) * span);
double c_low = average_cost(T_low, back, min_cost);
@@ -579,11 +559,6 @@ igraph_integer_t graph_molloy_hash::optimal_window() {
if (try_again--) {
continue;
}
- {
- igraph_status("Warning: when looking for optimal T,\n", 0);
- igraph_statusf("Low: %" IGRAPH_PRId " [%f] Middle: %" IGRAPH_PRId " [%f] High: %" IGRAPH_PRId " [%f]\n", 0,
- T_low, c_low, optimal_T, min_cost, T_high, c_high);
- }
delete[] back;
return optimal_T;
}
diff --git a/src/vendor/cigraph/src/games/erdos_renyi.c b/src/vendor/cigraph/src/games/erdos_renyi.c
index cb4bd55f729..d7a5b71be26 100644
--- a/src/vendor/cigraph/src/games/erdos_renyi.c
+++ b/src/vendor/cigraph/src/games/erdos_renyi.c
@@ -37,6 +37,31 @@
* they generate a different graph every time you call them.
*/
+/**
+ * \ingroup generators
+ * \function igraph_erdos_renyi_game_gnp
+ * \brief Generates a random (Erdős-Rényi) graph with fixed edge probabilities.
+ *
+ * In this model, a graph with n vertices is generated such that every possible
+ * edge is included in the graph with probability p.
+ *
+ * \param graph Pointer to an uninitialized graph object.
+ * \param n The number of vertices in the graph.
+ * \param p The probability of the existence of an edge in the graph.
+ * \param directed Logical, whether to generate a directed graph.
+ * \param loops Logical, whether to generate loops (self) edges.
+ * \return Error code:
+ * \c IGRAPH_EINVAL: invalid \p n or \p p parameter.
+ * \c IGRAPH_ENOMEM: there is not enough memory for the operation.
+ *
+ * Time complexity: O(|V|+|E|), the
+ * number of vertices plus the number of edges in the graph.
+ *
+ * \sa \ref igraph_barabasi_game(), \ref igraph_growing_random_game(),
+ * \ref igraph_erdos_renyi_game_gnm()
+ *
+ * \example examples/simple/igraph_erdos_renyi_game_gnp.c
+ */
igraph_error_t igraph_erdos_renyi_game_gnp(
igraph_t *graph, igraph_integer_t n, igraph_real_t p,
igraph_bool_t directed, igraph_bool_t loops
@@ -144,6 +169,31 @@ igraph_error_t igraph_erdos_renyi_game_gnp(
return IGRAPH_SUCCESS;
}
+/**
+ * \ingroup generators
+ * \function igraph_erdos_renyi_game_gnm
+ * \brief Generates a random (Erdős-Rényi) graph with a fixed number of edges.
+ *
+ * In this model, a graph with n vertices and m edges is generated such that the
+ * edges are selected uniformly at random.
+ *
+ * \param graph Pointer to an uninitialized graph object.
+ * \param n The number of vertices in the graph.
+ * \param m The number of edges in the graph.
+ * \param directed Logical, whether to generate a directed graph.
+ * \param loops Logical, whether to generate loops (self) edges.
+ * \return Error code:
+ * \c IGRAPH_EINVAL: invalid \p n or \p m parameter.
+ * \c IGRAPH_ENOMEM: there is not enough memory for the operation.
+ *
+ * Time complexity: O(|V|+|E|), the
+ * number of vertices plus the number of edges in the graph.
+ *
+ * \sa \ref igraph_barabasi_game(), \ref igraph_growing_random_game(),
+ * \ref igraph_erdos_renyi_game_gnp()
+ *
+ * \example examples/simple/igraph_erdos_renyi_game_gnm.c
+ */
igraph_error_t igraph_erdos_renyi_game_gnm(
igraph_t *graph, igraph_integer_t n, igraph_integer_t m,
igraph_bool_t directed, igraph_bool_t loops
@@ -249,6 +299,9 @@ igraph_error_t igraph_erdos_renyi_game_gnm(
* \function igraph_erdos_renyi_game
* \brief Generates a random (Erdős-Rényi) graph.
*
+ * This function is deprecated; use \ref igraph_erdos_renyi_game_gnm() or
+ * \ref igraph_erdos_renyi_game_gnp() instead.
+ *
* \param graph Pointer to an uninitialized graph object.
* \param type The type of the random graph, possible values:
* \clist
@@ -280,9 +333,8 @@ igraph_error_t igraph_erdos_renyi_game_gnm(
* Time complexity: O(|V|+|E|), the
* number of vertices plus the number of edges in the graph.
*
- * \sa \ref igraph_barabasi_game(), \ref igraph_growing_random_game()
- *
- * \example examples/simple/igraph_erdos_renyi_game.c
+ * \sa \ref igraph_barabasi_game(), \ref igraph_growing_random_game(),
+ * \ref igraph_erdos_renyi_game_gnm(), \ref igraph_erdos_renyi_game_gnp()
*/
igraph_error_t igraph_erdos_renyi_game(igraph_t *graph, igraph_erdos_renyi_t type,
igraph_integer_t n, igraph_real_t p_or_m,
diff --git a/src/vendor/cigraph/src/games/sbm.c b/src/vendor/cigraph/src/games/sbm.c
index 25e27dad3bf..d8c7a4bee62 100644
--- a/src/vendor/cigraph/src/games/sbm.c
+++ b/src/vendor/cigraph/src/games/sbm.c
@@ -68,7 +68,7 @@
* vertices, |E| is the number of edges, and K is the number of
* groups.
*
- * \sa \ref igraph_erdos_renyi_game() for a simple Bernoulli graph.
+ * \sa \ref igraph_erdos_renyi_game_gnp() for a simple Bernoulli graph.
*
*/
diff --git a/src/vendor/cigraph/src/graph/cattributes.c b/src/vendor/cigraph/src/graph/cattributes.c
index 1a341a39c30..2768e186ecf 100644
--- a/src/vendor/cigraph/src/graph/cattributes.c
+++ b/src/vendor/cigraph/src/graph/cattributes.c
@@ -518,7 +518,7 @@ static void igraph_i_attribute_permutation_work_area_release_stored_strvectors(
) {
if (work_area->strings != NULL) {
igraph_vector_ptr_destroy_all(work_area->strings);
- igraph_Free(work_area->strings);
+ IGRAPH_FREE(work_area->strings);
work_area->strings = NULL;
}
}
@@ -529,12 +529,12 @@ static void igraph_i_attribute_permutation_work_area_destroy(
igraph_i_attribute_permutation_work_area_release_stored_strvectors(work_area);
if (work_area->numeric != NULL) {
igraph_vector_destroy(work_area->numeric);
- igraph_Free(work_area->numeric);
+ IGRAPH_FREE(work_area->numeric);
work_area->numeric = NULL;
}
if (work_area->boolean != NULL) {
igraph_vector_bool_destroy(work_area->boolean);
- igraph_Free(work_area->boolean);
+ IGRAPH_FREE(work_area->boolean);
work_area->boolean = NULL;
}
}
diff --git a/src/vendor/cigraph/src/hrg/hrg.cc b/src/vendor/cigraph/src/hrg/hrg.cc
index 605bf150730..ee43f1c4bee 100644
--- a/src/vendor/cigraph/src/hrg/hrg.cc
+++ b/src/vendor/cigraph/src/hrg/hrg.cc
@@ -560,6 +560,70 @@ igraph_error_t igraph_hrg_game(igraph_t *graph,
return igraph_hrg_sample(hrg, graph);
}
+/**
+ * \function igraph_from_hrg_dendrogram
+ * \brief Create a graph representation of the dendrogram of a hierarchical random graph model.
+ *
+ * Creates the igraph graph equivalent of the dendrogram encoded in an
+ * \ref igraph_hrg_t data structure. The probabilities associated to the
+ * nodes are returned in a vector so this function works without an
+ * attribute handler.
+ *
+ * \param graph Pointer to an uninitialized graph, the result is
+ * stored here.
+ * \param hrg The hierarchical random graph to convert.
+ * \param prob Pointer to an \em initialized vector; the probabilities
+ * associated to the nodes of the dendrogram will be stored here. Leaf nodes
+ * will have an associated probability of \c IGRAPH_NAN .
+ * You may set this to \c NULL if you do not need the probabilities.
+ * \return Error code.
+ *
+ * Time complexity: O(n), the number of vertices in the graph.
+ */
+
+igraph_error_t igraph_from_hrg_dendrogram(
+ igraph_t *graph, const igraph_hrg_t *hrg, igraph_vector_t *prob
+) {
+ igraph_integer_t orig_nodes = igraph_hrg_size(hrg);
+ igraph_integer_t no_of_nodes = orig_nodes * 2 - 1;
+ igraph_integer_t no_of_edges = no_of_nodes > 0 ? no_of_nodes - 1 : 0;
+ igraph_vector_int_t edges;
+ igraph_integer_t i, idx = 0;
+
+ // Probability labels, for leaf nodes they are IGRAPH_NAN
+ if (prob) {
+ IGRAPH_CHECK(igraph_vector_resize(prob, no_of_nodes));
+ for (i = 0; i < orig_nodes; i++) {
+ VECTOR(*prob)[i] = IGRAPH_NAN;
+ }
+ for (i = 0; i < orig_nodes - 1; i++) {
+ VECTOR(*prob)[orig_nodes + i] = VECTOR(hrg->prob)[i];
+ }
+ }
+
+ IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges * 2);
+
+ for (i = 0; i < orig_nodes - 1; i++) {
+ igraph_integer_t left = VECTOR(hrg->left)[i];
+ igraph_integer_t right = VECTOR(hrg->right)[i];
+
+ VECTOR(edges)[idx++] = orig_nodes + i;
+ VECTOR(edges)[idx++] = left < 0 ? orig_nodes - left - 1 : left;
+ VECTOR(edges)[idx++] = orig_nodes + i;
+ VECTOR(edges)[idx++] = right < 0 ? orig_nodes - right - 1 : right;
+ }
+
+ IGRAPH_CHECK(igraph_empty(graph, 0, IGRAPH_DIRECTED));
+ IGRAPH_FINALLY(igraph_destroy, graph);
+ IGRAPH_CHECK(igraph_add_vertices(graph, no_of_nodes, NULL));
+ IGRAPH_CHECK(igraph_add_edges(graph, &edges, NULL));
+
+ igraph_vector_int_destroy(&edges);
+ IGRAPH_FINALLY_CLEAN(2); // + 1 for graph
+
+ return IGRAPH_SUCCESS;
+}
+
/**
* \function igraph_hrg_dendrogram
* \brief Create a dendrogram from a hierarchical random graph.
@@ -573,13 +637,11 @@ igraph_error_t igraph_hrg_game(igraph_t *graph,
* \return Error code.
*
* Time complexity: O(n), the number of vertices in the graph.
+ *
+ * \deprecated-by igraph_hrg_dendrogram 0.10.5
*/
-
-igraph_error_t igraph_hrg_dendrogram(
- igraph_t *graph, const igraph_hrg_t *hrg
-) {
-
- igraph_integer_t orig_nodes = igraph_hrg_size(hrg);
+igraph_error_t igraph_hrg_dendrogram(igraph_t *graph, const igraph_hrg_t *hrg) {
+ igraph_integer_t orig_nodes = igraph_hrg_size(hrg);
igraph_integer_t no_of_nodes = orig_nodes * 2 - 1;
igraph_integer_t no_of_edges = no_of_nodes > 0 ? no_of_nodes - 1 : 0;
igraph_vector_int_t edges;
diff --git a/src/vendor/cigraph/src/io/parse_utils.c b/src/vendor/cigraph/src/io/parse_utils.c
index 8fa17c84c41..6fc4b3d1b66 100644
--- a/src/vendor/cigraph/src/io/parse_utils.c
+++ b/src/vendor/cigraph/src/io/parse_utils.c
@@ -28,7 +28,7 @@
* igraph_i_trim_whitespace(str, strlen(str), &res, &len);
*
* This does not carry a performance penalty, as the end of the string would need to be
- * determinted anyway.
+ * determined anyway.
*/
void igraph_i_trim_whitespace(const char *str, size_t str_len, const char **res, size_t *res_len) {
const char *beg = str, *end = str + str_len;
@@ -43,7 +43,7 @@ void igraph_i_trim_whitespace(const char *str, size_t str_len, const char **res,
/* Converts a string to an integer. Throws an error if the result is not representable.
*
- * The input is a not-necesarily-null-terminated string that must contain only the number.
+ * The input is a not-necessarily-null-terminated string that must contain only the number.
* Any additional characters at the end of the string, such as whitespace, will trigger
* a parsing error.
*
@@ -64,9 +64,7 @@ igraph_error_t igraph_i_parse_integer(const char *str, size_t length, igraph_int
if (dynamic_alloc) {
tmp = IGRAPH_CALLOC(length+1, char);
- if (tmp == NULL) {
- IGRAPH_ERROR("Failed to parse integer.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
- }
+ IGRAPH_CHECK_OOM(tmp, "Failed to parse integer.");
} else {
tmp = buffer;
}
@@ -106,7 +104,7 @@ igraph_error_t igraph_i_parse_integer(const char *str, size_t length, igraph_int
/* Converts a string to a real number. Throws an error if the result is not representable.
*
- * The input is a not-necesarily-null-terminated string that must contain only the number.
+ * The input is a not-necessarily-null-terminated string that must contain only the number.
* Any additional characters at the end of the string, such as whitespace, will trigger
* a parsing error.
*
@@ -126,9 +124,7 @@ igraph_error_t igraph_i_parse_real(const char *str, size_t length, igraph_real_t
if (dynamic_alloc) {
tmp = IGRAPH_CALLOC(length+1, char);
- if (tmp == NULL) {
- IGRAPH_ERROR("Failed to parse real number.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
- }
+ IGRAPH_CHECK_OOM(tmp, "Failed to parse real number.");
} else {
tmp = buffer;
}
@@ -279,7 +275,7 @@ igraph_error_t igraph_i_fget_real(FILE *file, igraph_real_t *value) {
* numbers uses a decimal point instead of a comma.
*
* These functions attempt to set the locale only for the current thread on a best-effort
- * basis. On some platforms this is not possible, so the global locale will be changes.
+ * basis. On some platforms this is not possible, so the global locale will be changed.
* This is not safe to do in multi-threaded programs (not even if igraph runs only in
* a single thread).
*/
@@ -304,7 +300,7 @@ struct igraph_safelocale_s {
*
* igraph's foreign format readers and writers require a locale that uses a
* decimal point instead of a decimal comma. This is a convenience function
- * that temporarily sets the C locale so that readers and writer would work
+ * that temporarily sets the C locale so that readers and writers would work
* correctly. It \em must be paired with a call to \ref igraph_exit_safelocale(),
* otherwise a memory leak will occur.
*
@@ -343,9 +339,7 @@ igraph_error_t igraph_enter_safelocale(igraph_safelocale_t *loc) {
l->original_locale = uselocale(l->c_locale);
#else
l->original_locale = strdup(setlocale(LC_NUMERIC, NULL));
- if (! l->original_locale) {
- IGRAPH_ERROR("Not enough memory.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
- }
+ IGRAPH_CHECK_OOM(l->original_locale, "Not enough memory.");
# ifdef HAVE__CONFIGTHREADLOCALE
/* On Windows, we can enable per-thread locale */
l->per_thread_locale = _configthreadlocale(0);
diff --git a/src/vendor/cigraph/src/isomorphism/bliss/CMakeLists.txt b/src/vendor/cigraph/src/isomorphism/bliss/CMakeLists.txt
index 276bf80d809..9de271afb6b 100644
--- a/src/vendor/cigraph/src/isomorphism/bliss/CMakeLists.txt
+++ b/src/vendor/cigraph/src/isomorphism/bliss/CMakeLists.txt
@@ -31,7 +31,7 @@ endif()
if(NOT GMP_IS_VENDORED)
target_link_libraries(
bliss
- PUBLIC
+ PRIVATE
${GMP_LIBRARY}
)
endif()
diff --git a/src/vendor/cigraph/src/isomorphism/queries.c b/src/vendor/cigraph/src/isomorphism/queries.c
index 2528a9ae4d0..1337fd8e3a7 100644
--- a/src/vendor/cigraph/src/isomorphism/queries.c
+++ b/src/vendor/cigraph/src/isomorphism/queries.c
@@ -69,15 +69,13 @@ static igraph_error_t igraph_i_isomorphic_small(
* first graph into the edge set of the second. This mapping is called
* an \em isomorphism.
*
- * Currently, this function supports simple graphs and graphs
- * with self-loops, but does not support multigraphs.
- *
* This function decides which graph isomorphism algorithm to be
* used based on the input graphs. Right now it does the following:
* \olist
* \oli If one graph is directed and the other undirected then an
* error is triggered.
- * \oli If one of the graphs has multi-edges then an error is triggered.
+ * \oli If one of the graphs has multi-edges then both graphs are
+ * simplified and colorized using \ref igraph_simplify_and_colorize() and sent to VF2.
* \oli If the two graphs does not have the same number of vertices
* and edges it returns with \c false.
* \oli Otherwise, if the \ref igraph_isoclass() function supports both
@@ -108,17 +106,44 @@ igraph_error_t igraph_isomorphic(const igraph_t *graph1, const igraph_t *graph2,
igraph_bool_t dir1 = igraph_is_directed(graph1), dir2 = igraph_is_directed(graph2);
igraph_bool_t loop1, loop2, multi1, multi2;
+ if (dir1 != dir2) {
+ IGRAPH_ERROR("Cannot compare directed and undirected graphs for isomorphism.", IGRAPH_EINVAL);
+ }
+
IGRAPH_CHECK(igraph_has_multiple(graph1, &multi1));
IGRAPH_CHECK(igraph_has_multiple(graph2, &multi2));
if (multi1 || multi2) {
- IGRAPH_ERROR("Isomorphism testing is not implemented for multigraphs", IGRAPH_UNIMPLEMENTED);
+ igraph_t r1;
+ igraph_t r2;
+ igraph_vector_int_t vc1;
+ igraph_vector_int_t vc2;
+ igraph_vector_int_t ec1;
+ igraph_vector_int_t ec2;
+
+ IGRAPH_VECTOR_INT_INIT_FINALLY(&vc1, 0);
+ IGRAPH_VECTOR_INT_INIT_FINALLY(&vc2, 0);
+ IGRAPH_VECTOR_INT_INIT_FINALLY(&ec1, 0);
+ IGRAPH_VECTOR_INT_INIT_FINALLY(&ec2, 0);
+ IGRAPH_CHECK(igraph_simplify_and_colorize(graph1, &r1, &vc1, &ec1));
+ IGRAPH_FINALLY(igraph_destroy, &r1);
+ IGRAPH_CHECK(igraph_simplify_and_colorize(graph2, &r2, &vc2, &ec2));
+ IGRAPH_FINALLY(igraph_destroy, &r2);
+ IGRAPH_CHECK(igraph_isomorphic_vf2(&r1, &r2, &vc1, &vc2, &ec1, &ec2, iso,
+ NULL, NULL, NULL, NULL, NULL));
+ igraph_destroy(&r2);
+ igraph_destroy(&r1);
+ igraph_vector_int_destroy(&ec2);
+ igraph_vector_int_destroy(&ec1);
+ igraph_vector_int_destroy(&vc2);
+ igraph_vector_int_destroy(&vc1);
+ IGRAPH_FINALLY_CLEAN(6);
+
+ return IGRAPH_SUCCESS;
}
- if (dir1 != dir2) {
- IGRAPH_ERROR("Cannot compare directed and undirected graphs", IGRAPH_EINVAL);
- } else if (nodes1 != nodes2 || edges1 != edges2) {
- *iso = 0;
+ if (nodes1 != nodes2 || edges1 != edges2) {
+ *iso = false;
} else if (nodes1 >= 3 && nodes1 <= (dir1 ? 4 : 6)) {
IGRAPH_CHECK(igraph_has_loop(graph1, &loop1));
IGRAPH_CHECK(igraph_has_loop(graph2, &loop2));
@@ -126,11 +151,11 @@ igraph_error_t igraph_isomorphic(const igraph_t *graph1, const igraph_t *graph2,
IGRAPH_CHECK(igraph_i_isomorphic_small(graph1, graph2, iso));
} else {
IGRAPH_CHECK(igraph_isomorphic_bliss(graph1, graph2, NULL, NULL, iso,
- 0, 0, /*sh=*/ IGRAPH_BLISS_FL, 0, 0));
+ NULL, NULL, /*sh=*/ IGRAPH_BLISS_FL, NULL, NULL));
}
} else {
IGRAPH_CHECK(igraph_isomorphic_bliss(graph1, graph2, NULL, NULL, iso,
- 0, 0, /*sh=*/ IGRAPH_BLISS_FL, 0, 0));
+ NULL, NULL, /*sh=*/ IGRAPH_BLISS_FL, NULL, NULL));
}
return IGRAPH_SUCCESS;
diff --git a/src/vendor/cigraph/src/math/utils.c b/src/vendor/cigraph/src/math/utils.c
index 71150359ecd..7c0be5baf4f 100644
--- a/src/vendor/cigraph/src/math/utils.c
+++ b/src/vendor/cigraph/src/math/utils.c
@@ -91,11 +91,25 @@ igraph_bool_t igraph_almost_equals(double a, double b, double eps) {
* Determines whether two double-precision floats are "almost equal"
* to each other with a given level of tolerance on the relative error.
*
+ *
+ * The function supports infinities and NaN values. NaN values are considered
+ * not equal to any other value (even another NaN), but the ordering is
+ * arbitrary; in other words, we only guarantee that comparing a NaN with
+ * any other value will not return zero. Positive infinity is considered to
+ * be greater than any finite value with any tolerance. Negative infinity is
+ * considered to be smaller than any finite value with any tolerance.
+ * Positive infinity is considered to be equal to another positive infinity
+ * with any tolerance. Negative infinity is considered to be equal to another
+ * negative infinity with any tolerance.
+ *
* \param a The first float.
* \param b The second float.
* \param eps The level of tolerance on the relative error. The relative
* error is defined as abs(a-b) / (abs(a) + abs(b)). The
* two numbers are considered equal if this is less than \c eps.
+ * Negative epsilon values are not allowed; the returned value will
+ * be undefined in this case. Zero means to do an exact comparison
+ * without tolerance.
*
* \return Zero if the two floats are nearly equal to each other within
* the given level of tolerance, positive number if the first float is
diff --git a/src/vendor/cigraph/src/misc/motifs.c b/src/vendor/cigraph/src/misc/motifs.c
index 2b0231bed91..2fdd1cc33ab 100644
--- a/src/vendor/cigraph/src/misc/motifs.c
+++ b/src/vendor/cigraph/src/misc/motifs.c
@@ -309,15 +309,11 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte
}
added = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t);
- if (added == 0) {
- IGRAPH_ERROR("Cannot find motifs", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
- }
+ IGRAPH_CHECK_OOM(added, "Insufficient memory to find motifs.");
IGRAPH_FINALLY(igraph_free, added);
subg = IGRAPH_CALLOC(no_of_nodes, char);
- if (subg == 0) {
- IGRAPH_ERROR("Cannot find motifs", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
- }
+ IGRAPH_CHECK_OOM(subg, "Insufficient memory to find motifs.");
IGRAPH_FINALLY(igraph_free, subg);
IGRAPH_CHECK(igraph_adjlist_init(graph, &allneis, IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE));
@@ -504,32 +500,26 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte
* \function igraph_motifs_randesu_estimate
* \brief Estimate the total number of motifs in a graph.
*
- * This function estimates the total number of weakly connected induced
- * subgraphs, called motifs, of a fixed number of vertices. For
- * example, an undirected complete graph on \c n vertices
- * will have one motif of size \c n, and \c n motifs
+ * This function estimates the total number of (weakly) connected induced
+ * subgraphs on \p size vertices. For example, an undirected complete graph
+ * on \c n vertices will have one motif of size \c n, and \c n motifs
* of \p size n - 1. As another example, one triangle
* and a separate vertex will have zero motifs of size four.
*
*
* This function is useful for large graphs for which it is not
- * feasible to count all the different motifs, because there are very
+ * feasible to count all connected subgraphs, as there are too
* many of them.
*
*
- * The total number of motifs is estimated by taking a sample of
- * vertices and counts all motifs in which these vertices are
- * included. (There is also a \p cut_prob parameter which gives the
- * probabilities to cut a branch of the search tree.)
- *
- *
- * Directed motifs will be counted in directed graphs and undirected
- * motifs in undirected graphs.
+ * The estimate is made by taking a sample of vertices and counting all
+ * connected subgraphs in which these vertices are included. There is also
+ * a \p cut_prob parameter which gives the probabilities to cut a branch of
+ * the search tree.
*
* \param graph The graph object to study.
- * \param est Pointer to an integer type, the result will be stored
- * here.
- * \param size The size of the motifs to look for.
+ * \param est Pointer to an integer, the result will be stored here.
+ * \param size The size of the subgraphs to look for.
* \param cut_prob Vector giving the probabilities to cut a branch of
* the search tree and omit counting the motifs in that branch.
* It contains a probability for each level. Supply \p size
@@ -543,6 +533,7 @@ igraph_error_t igraph_motifs_randesu_callback(const igraph_t *graph, igraph_inte
* argument is used to create a sample of vertices drawn with
* uniform probability.
* \return Error code.
+ *
* \sa \ref igraph_motifs_randesu(), \ref igraph_motifs_randesu_no().
*
* Time complexity: TODO.
@@ -584,9 +575,7 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_inte
}
added = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t);
- if (added == 0) {
- IGRAPH_ERROR("Cannot find motifs.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
- }
+ IGRAPH_CHECK_OOM(added, "Insufficient memory to count motifs.");
IGRAPH_FINALLY(igraph_free, added);
IGRAPH_VECTOR_INT_INIT_FINALLY(&vids, 0);
@@ -597,9 +586,7 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_inte
if (parsample == NULL) {
sample = IGRAPH_CALLOC(1, igraph_vector_int_t);
- if (sample == NULL) {
- IGRAPH_ERROR("Cannot estimate motifs.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
- }
+ IGRAPH_CHECK_OOM(sample, "Insufficient memory to count motifs.");
IGRAPH_FINALLY(igraph_free, sample);
IGRAPH_VECTOR_INT_INIT_FINALLY(sample, 0);
IGRAPH_CHECK(igraph_random_sample(sample, 0, no_of_nodes - 1, sample_size));
@@ -744,10 +731,9 @@ igraph_error_t igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_inte
* \function igraph_motifs_randesu_no
* \brief Count the total number of motifs in a graph.
*
- *
- * This function counts the total number of motifs in a graph,
- * i.e. the number of of (weakly) connected triplets or quadruplets,
- * without assigning isomorphism classes to them.
+ * This function counts the total number of (weakly) connected
+ * induced subgraphs on \p size vertices, without assigning isomorphism
+ * classes to them. Arbitrarily large motif sizes are supported.
*
* \param graph The graph object to study.
* \param no Pointer to an integer type, the result will be stored
@@ -784,9 +770,7 @@ igraph_error_t igraph_motifs_randesu_no(const igraph_t *graph, igraph_integer_t
IGRAPH_EINVAL, igraph_vector_size(cut_prob), size);
}
added = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t);
- if (added == 0) {
- IGRAPH_ERROR("Cannot find motifs.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
- }
+ IGRAPH_CHECK_OOM(added, "Insufficient memory to count motifs.");
IGRAPH_FINALLY(igraph_free, added);
IGRAPH_VECTOR_INT_INIT_FINALLY(&vids, 0);
diff --git a/src/vendor/cigraph/src/misc/scan.c b/src/vendor/cigraph/src/misc/scan.c
index 7fa64730ddf..6e96595b2e4 100644
--- a/src/vendor/cigraph/src/misc/scan.c
+++ b/src/vendor/cigraph/src/misc/scan.c
@@ -244,96 +244,6 @@ static igraph_error_t igraph_i_local_scan_1_directed_all(const igraph_t *graph,
return IGRAPH_SUCCESS;
}
-static igraph_error_t igraph_i_local_scan_1_sumweights(const igraph_t *graph,
- igraph_vector_t *res,
- const igraph_vector_t *weights) {
-
- igraph_integer_t no_of_nodes = igraph_vcount(graph);
- igraph_integer_t node, i, j, nn;
- igraph_inclist_t allinc;
- igraph_vector_int_t *neis1, *neis2;
- igraph_integer_t neilen1, neilen2;
- igraph_integer_t *neis;
- igraph_integer_t maxdegree;
-
- igraph_vector_int_t order;
- igraph_vector_int_t rank;
- igraph_vector_int_t degree, *edge1 = °ree; /* reuse degree as edge1 */
-
- if (igraph_vector_size(weights) != igraph_ecount(graph)) {
- IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL);
- }
-
- IGRAPH_VECTOR_INT_INIT_FINALLY(&order, no_of_nodes);
- IGRAPH_VECTOR_INT_INIT_FINALLY(°ree, no_of_nodes);
-
- IGRAPH_CHECK(igraph_degree(graph, °ree, igraph_vss_all(), IGRAPH_ALL,
- IGRAPH_LOOPS));
- maxdegree = igraph_vector_int_max(°ree) + 1;
- IGRAPH_CHECK(igraph_vector_int_order1(°ree, &order, maxdegree));
- IGRAPH_VECTOR_INT_INIT_FINALLY(&rank, no_of_nodes);
- for (i = 0; i < no_of_nodes; i++) {
- VECTOR(rank)[ VECTOR(order)[i] ] = no_of_nodes - i - 1;
- }
-
- IGRAPH_CHECK(igraph_inclist_init(graph, &allinc, IGRAPH_ALL, IGRAPH_LOOPS_TWICE));
- IGRAPH_FINALLY(igraph_inclist_destroy, &allinc);
- IGRAPH_CHECK(igraph_i_trans4_il_simplify(graph, &allinc, &rank));
-
- neis = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t);
- if (neis == 0) {
- IGRAPH_ERROR("undirected local transitivity failed", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
- }
- IGRAPH_FINALLY(igraph_free, neis);
-
- IGRAPH_CHECK(igraph_strength(graph, res, igraph_vss_all(), IGRAPH_ALL,
- IGRAPH_LOOPS, weights));
-
- for (nn = no_of_nodes - 1; nn >= 0; nn--) {
- node = VECTOR(order)[nn];
-
- IGRAPH_ALLOW_INTERRUPTION();
-
- neis1 = igraph_inclist_get(&allinc, node);
- neilen1 = igraph_vector_int_size(neis1);
-
- /* Mark the neighbors of the node */
- for (i = 0; i < neilen1; i++) {
- igraph_integer_t edge = VECTOR(*neis1)[i];
- igraph_integer_t nei = IGRAPH_OTHER(graph, edge, node);
- VECTOR(*edge1)[nei] = VECTOR(*weights)[edge];
- neis[nei] = node + 1;
- }
-
- for (i = 0; i < neilen1; i++) {
- igraph_integer_t edge = VECTOR(*neis1)[i];
- igraph_integer_t nei = IGRAPH_OTHER(graph, edge, node);
- igraph_real_t w = VECTOR(*weights)[edge];
- neis2 = igraph_inclist_get(&allinc, nei);
- neilen2 = igraph_vector_int_size(neis2);
- for (j = 0; j < neilen2; j++) {
- igraph_integer_t edge2 = VECTOR(*neis2)[j];
- igraph_integer_t nei2 = IGRAPH_OTHER(graph, edge2, nei);
- igraph_real_t w2 = VECTOR(*weights)[edge2];
- if (neis[nei2] == node + 1) {
- VECTOR(*res)[node] += w2;
- VECTOR(*res)[nei2] += w;
- VECTOR(*res)[nei] += VECTOR(*edge1)[nei2];
- }
- }
- }
- }
-
- igraph_free(neis);
- igraph_inclist_destroy(&allinc);
- igraph_vector_int_destroy(&rank);
- igraph_vector_int_destroy(°ree);
- igraph_vector_int_destroy(&order);
- IGRAPH_FINALLY_CLEAN(5);
-
- return IGRAPH_SUCCESS;
-}
-
/**
* \function igraph_local_scan_1_ecount
* Local scan-statistics, k=1, edge count and sum of weights
@@ -362,11 +272,7 @@ igraph_error_t igraph_local_scan_1_ecount(const igraph_t *graph, igraph_vector_t
return igraph_i_local_scan_1_directed_all(graph, res, weights);
}
} else {
- if (weights) {
- return igraph_i_local_scan_1_sumweights(graph, res, weights);
- } else {
- return igraph_local_scan_k_ecount(graph, 1, res, weights, mode);
- }
+ return igraph_local_scan_k_ecount(graph, 1, res, weights, mode);
}
}
diff --git a/src/vendor/cigraph/src/operators/simplify.c b/src/vendor/cigraph/src/operators/simplify.c
index 3dd804cbb77..d100dd0b104 100644
--- a/src/vendor/cigraph/src/operators/simplify.c
+++ b/src/vendor/cigraph/src/operators/simplify.c
@@ -33,6 +33,10 @@
* \function igraph_simplify
* \brief Removes loop and/or multiple edges from the graph.
*
+ * This function merges parallel edges and removes self-loops, according
+ * to the \p multiple and \p loops parameters. Note that this function
+ * may change the edge order, even if the input was already a simple graph.
+ *
* \param graph The graph object.
* \param multiple Logical, if true, multiple edges will be removed.
* \param loops Logical, if true, loops (self edges) will be removed.
@@ -48,9 +52,9 @@
* \example examples/simple/igraph_simplify.c
*/
-igraph_error_t igraph_simplify(igraph_t *graph, igraph_bool_t multiple,
- igraph_bool_t loops,
- const igraph_attribute_combination_t *edge_comb) {
+igraph_error_t igraph_simplify(igraph_t *graph,
+ igraph_bool_t multiple, igraph_bool_t loops,
+ const igraph_attribute_combination_t *edge_comb) {
igraph_vector_int_t edges;
igraph_integer_t no_of_nodes = igraph_vcount(graph);
@@ -64,6 +68,18 @@ igraph_error_t igraph_simplify(igraph_t *graph, igraph_bool_t multiple,
igraph_vector_int_t mergeinto;
igraph_integer_t actedge;
+ /* if we already know there are no multi-edges, they don't need to be removed */
+ if (igraph_i_property_cache_has(graph, IGRAPH_PROP_HAS_MULTI) &&
+ !igraph_i_property_cache_get_bool(graph, IGRAPH_PROP_HAS_MULTI)) {
+ multiple = false;
+ }
+
+ /* if we already know there are no loops, they don't need to be removed */
+ if (igraph_i_property_cache_has(graph, IGRAPH_PROP_HAS_LOOP) &&
+ !igraph_i_property_cache_get_bool(graph, IGRAPH_PROP_HAS_LOOP)) {
+ loops = false;
+ }
+
if (!multiple && !loops)
/* nothing to do */
{
@@ -102,6 +118,8 @@ igraph_error_t igraph_simplify(igraph_t *graph, igraph_bool_t multiple,
igraph_vector_int_destroy(&edges_to_delete);
IGRAPH_FINALLY_CLEAN(1);
+ igraph_i_property_cache_set_bool(graph, IGRAPH_PROP_HAS_LOOP, false);
+
return IGRAPH_SUCCESS;
}
@@ -133,8 +151,8 @@ igraph_error_t igraph_simplify(igraph_t *graph, igraph_bool_t multiple,
}
} else {
/* Edge to be kept */
- igraph_vector_int_push_back(&edges, from);
- igraph_vector_int_push_back(&edges, to);
+ igraph_vector_int_push_back(&edges, from); /* reserved */
+ igraph_vector_int_push_back(&edges, to); /* reserved */
if (attr) {
actedge++;
VECTOR(mergeinto)[edge] = actedge;
@@ -155,8 +173,7 @@ igraph_error_t igraph_simplify(igraph_t *graph, igraph_bool_t multiple,
IGRAPH_FINALLY(igraph_destroy, &res);
IGRAPH_I_ATTRIBUTE_DESTROY(&res);
- IGRAPH_I_ATTRIBUTE_COPY(&res, graph, /*graph=*/ 1,
- /*vertex=*/ 1, /*edge=*/ 0);
+ IGRAPH_I_ATTRIBUTE_COPY(&res, graph, /*graph=*/ true, /*vertex=*/ true, /*edge=*/ false);
if (attr) {
igraph_fixed_vectorlist_t vl;
@@ -174,5 +191,20 @@ igraph_error_t igraph_simplify(igraph_t *graph, igraph_bool_t multiple,
igraph_destroy(graph);
*graph = res;
+ /* The cache must be set as the very last step, only after all functions that can
+ * potentially return with an error have finished. */
+
+ if (loops) {
+ /* Loop edges were removed so we know for sure that there aren't any
+ * loop edges now */
+ igraph_i_property_cache_set_bool(graph, IGRAPH_PROP_HAS_LOOP, false);
+ }
+
+ if (multiple) {
+ /* Multi-edges were removed so we know for sure that there aren't any
+ * multi-edges now */
+ igraph_i_property_cache_set_bool(graph, IGRAPH_PROP_HAS_MULTI, false);
+ }
+
return IGRAPH_SUCCESS;
}
diff --git a/src/vendor/cigraph/src/paths/astar.c b/src/vendor/cigraph/src/paths/astar.c
index 3660f65e4b6..c3d5f55c822 100644
--- a/src/vendor/cigraph/src/paths/astar.c
+++ b/src/vendor/cigraph/src/paths/astar.c
@@ -71,7 +71,7 @@ static igraph_error_t null_heuristic(
* \param weights Optional edge weights. Supply \c NULL for unweighted graphs.
* All edge weights must be non-negative. Additionally, no
* edge weight may be NaN. If either case does not hold, an error
- * is returned.
+ * is returned. Edges with positive infinite weights are ignored.
* \param mode A constant specifying how edge directions are
* considered in directed graphs. \c IGRAPH_OUT follows edge
* directions, \c IGRAPH_IN follows the opposite directions,
@@ -151,7 +151,7 @@ igraph_error_t igraph_get_shortest_path_astar(const igraph_t *graph,
/* parent_eids[v] is the 1 + the ID of v's inbound edge in the shortest path tree.
* A value of 0 indicates unreachable vertices. */
parent_eids = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t);
- IGRAPH_CHECK_OOM(parent_eids, "Can't calculate shortest paths.");
+ IGRAPH_CHECK_OOM(parent_eids, "Insufficient memory for shortest paths with A* algorithm.");
IGRAPH_FINALLY(igraph_free, parent_eids);
VECTOR(dists)[from] = 0.0;
@@ -194,9 +194,9 @@ igraph_error_t igraph_get_shortest_path_astar(const igraph_t *graph,
igraph_real_t altdist; /* candidate from -> v distance */
if (weights) {
igraph_real_t weight = VECTOR(*weights)[edge];
- /* TODO: Should infinite-weight edges be skipped?
- * See https://github.com/igraph/igraph/issues/2222 */
- if (weight == IGRAPH_INFINITY) continue;
+ if (weight == IGRAPH_INFINITY) {
+ continue;
+ }
altdist = VECTOR(dists)[u] + weight;
} else {
altdist = VECTOR(dists)[u] + 1;
diff --git a/src/vendor/cigraph/src/paths/bellman_ford.c b/src/vendor/cigraph/src/paths/bellman_ford.c
index 2bfaadb288e..e5023e9eafe 100644
--- a/src/vendor/cigraph/src/paths/bellman_ford.c
+++ b/src/vendor/cigraph/src/paths/bellman_ford.c
@@ -264,6 +264,7 @@ igraph_error_t igraph_shortest_paths_bellman_ford(const igraph_t *graph,
* us to decrease the weight of any path containing at least a single
* vertex of this loop infinitely). If this is a null pointer, then the
* unweighted version, \ref igraph_get_shortest_paths() is called.
+ * Edges with positive infinite weights are ignored.
* \param mode For directed graphs; whether to follow paths along edge
* directions (\c IGRAPH_OUT), or the opposite (\c IGRAPH_IN), or
* ignore edge directions completely (\c IGRAPH_ALL). It is ignored
@@ -396,6 +397,11 @@ igraph_error_t igraph_get_shortest_paths_bellman_ford(const igraph_t *graph,
igraph_integer_t nei = VECTOR(*neis)[k];
igraph_integer_t target = IGRAPH_OTHER(graph, nei, j);
igraph_real_t altdist = VECTOR(dist)[j] + VECTOR(*weights)[nei];
+
+ /* infinite weights are handled correctly here; if an edge has
+ * infinite weight, altdist will also be infinite so the condition
+ * will never be true as if the edge was ignored */
+
if (VECTOR(dist)[target] > altdist) {
/* relax the edge */
VECTOR(dist)[target] = altdist;
diff --git a/src/vendor/cigraph/src/paths/dijkstra.c b/src/vendor/cigraph/src/paths/dijkstra.c
index 9207b52a0ca..aa0d7b57ebb 100644
--- a/src/vendor/cigraph/src/paths/dijkstra.c
+++ b/src/vendor/cigraph/src/paths/dijkstra.c
@@ -58,7 +58,8 @@
* non-negative for Dijkstra's algorithm to work. Additionally, no
* edge weight may be NaN. If either case does not hold, an error
* is returned. If this is a null pointer, then the unweighted
- * version, \ref igraph_distances() is called.
+ * version, \ref igraph_distances() is called. Edges with positive infinite
+ * weights are ignored.
* \param mode For directed graphs; whether to follow paths along edge
* directions (\c IGRAPH_OUT), or the opposite (\c IGRAPH_IN), or
* ignore edge directions completely (\c IGRAPH_ALL). It is ignored
@@ -212,7 +213,9 @@ igraph_error_t igraph_distances_dijkstra_cutoff(const igraph_t *graph,
igraph_real_t weight = VECTOR(*weights)[edge];
/* Optimization: do not follow infinite-weight edges. */
- if (weight == IGRAPH_INFINITY) continue;
+ if (weight == IGRAPH_INFINITY) {
+ continue;
+ }
igraph_integer_t tto = IGRAPH_OTHER(graph, edge, minnei);
igraph_real_t altdist = mindist + weight;
@@ -465,21 +468,18 @@ igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t *graph,
igraph_vector_fill(&dists, -1.0);
parent_eids = IGRAPH_CALLOC(no_of_nodes, igraph_integer_t);
- if (parent_eids == 0) {
- IGRAPH_ERROR("Can't calculate shortest paths", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
- }
+ IGRAPH_CHECK_OOM(parent_eids, "Insufficient memory for shortest paths with Dijkstra's algorithm.");
IGRAPH_FINALLY(igraph_free, parent_eids);
+
is_target = IGRAPH_CALLOC(no_of_nodes, igraph_bool_t);
- if (is_target == 0) {
- IGRAPH_ERROR("Can't calculate shortest paths", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
- }
+ IGRAPH_CHECK_OOM(is_target, "Insufficient memory for shortest paths with Dijkstra's algorithm.");
IGRAPH_FINALLY(igraph_free, is_target);
/* Mark the vertices we need to reach */
to_reach = IGRAPH_VIT_SIZE(vit);
for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) {
if (!is_target[ IGRAPH_VIT_GET(vit) ]) {
- is_target[ IGRAPH_VIT_GET(vit) ] = 1;
+ is_target[ IGRAPH_VIT_GET(vit) ] = true;
} else {
to_reach--; /* this node was given multiple times */
}
@@ -497,7 +497,7 @@ igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t *graph,
IGRAPH_ALLOW_INTERRUPTION();
if (is_target[minnei]) {
- is_target[minnei] = 0;
+ is_target[minnei] = false;
to_reach--;
}
@@ -525,7 +525,7 @@ igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t *graph,
} /* !igraph_2wheap_empty(&Q) */
if (to_reach > 0) {
- IGRAPH_WARNING("Couldn't reach some vertices");
+ IGRAPH_WARNING("Couldn't reach some vertices.");
}
/* Create `parents' if needed */
@@ -837,14 +837,14 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph,
igraph_vector_int_t *parent_vec, *parent_edge_vec;
parent_vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
- IGRAPH_CHECK_OOM(parent_vec, "Cannot calculate shortest paths.");
+ IGRAPH_CHECK_OOM(parent_vec, "Insufficient memory for all shortest paths with Dijkstra's algorithm.");
IGRAPH_FINALLY(igraph_free, parent_vec);
IGRAPH_CHECK(igraph_vector_int_init(parent_vec, 0));
VECTOR(parents)[i] = parent_vec;
IGRAPH_FINALLY_CLEAN(1);
parent_edge_vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
- IGRAPH_CHECK_OOM(parent_edge_vec, "Cannot calculate shortest paths.");
+ IGRAPH_CHECK_OOM(parent_edge_vec, "Insufficient memory for all shortest paths with Dijkstra's algorithm.");
IGRAPH_FINALLY(igraph_free, parent_edge_vec);
IGRAPH_CHECK(igraph_vector_int_init(parent_edge_vec, 0));
VECTOR(parents_edge)[i] = parent_edge_vec;
@@ -861,7 +861,7 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph,
/* boolean array to mark whether a given vertex is a target or not */
is_target = IGRAPH_CALLOC(no_of_nodes, unsigned char);
- IGRAPH_CHECK_OOM(is_target, "Cannot calculate shortest paths.");
+ IGRAPH_CHECK_OOM(is_target, "Insufficient memory for all shortest paths with Dijkstra's algorithm.");
IGRAPH_FINALLY(igraph_free, is_target);
/* two-way heap storing vertices and distances */
@@ -1079,7 +1079,7 @@ igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph,
/* If the 'vertices' vector doesn't exist, then create one, in order
* for the algorithm to work. */
vertices = IGRAPH_CALLOC(1, igraph_vector_int_list_t);
- IGRAPH_CHECK_OOM(vertices, "Cannot calculate shortest paths.");
+ IGRAPH_CHECK_OOM(vertices, "Insufficient memory for all shortest paths with Dijkstra's algorithm.");
IGRAPH_FINALLY(igraph_free, vertices);
IGRAPH_VECTOR_INT_LIST_INIT_FINALLY(vertices, 0);
free_vertices = true;
diff --git a/src/vendor/cigraph/src/paths/distances.c b/src/vendor/cigraph/src/paths/distances.c
index 66408de4889..e14a13c5a07 100644
--- a/src/vendor/cigraph/src/paths/distances.c
+++ b/src/vendor/cigraph/src/paths/distances.c
@@ -171,7 +171,10 @@ static igraph_error_t igraph_i_eccentricity_dijkstra(
igraph_bool_t active = igraph_2wheap_has_active(&Q, tto);
igraph_bool_t has = igraph_2wheap_has_elem(&Q, tto);
igraph_real_t curdist = active ? -igraph_2wheap_get(&Q, tto) : 0.0;
- if (!has) {
+
+ if (altdist == IGRAPH_INFINITY) {
+ /* Ignore edges with positive infinite weights */
+ } else if (!has) {
/* This is the first non-infinite distance */
IGRAPH_CHECK(igraph_2wheap_push_with_index(&Q, tto, -altdist));
} else if (altdist < curdist) {
@@ -288,7 +291,8 @@ igraph_error_t igraph_eccentricity(const igraph_t *graph,
* non-negative for Dijkstra's algorithm to work. Additionally, no
* edge weight may be NaN. If either case does not hold, an error
* is returned. If this is a null pointer, then the unweighted
- * version, \ref igraph_eccentricity() is called.
+ * version, \ref igraph_eccentricity() is called. Edges with positive
+ * infinite weights are ignored.
* \param res Pointer to an initialized vector, the result is stored
* here.
* \param vids The vertices for which the eccentricity is calculated.
@@ -644,7 +648,8 @@ igraph_error_t igraph_pseudo_diameter(const igraph_t *graph,
*
* \param graph The input graph, can be directed or undirected.
* \param weights The edge weights of the graph. Can be \c NULL for an
- * unweighted graph. All weights should be non-negative.
+ * unweighted graph. All weights should be non-negative. Edges with
+ * positive infinite weights are ignored.
* \param diameter This will contain the weighted pseudo-diameter.
* \param vid_start Id of the starting vertex. If this is negative, a
* random starting vertex is chosen.
diff --git a/src/vendor/cigraph/src/paths/floyd_warshall.c b/src/vendor/cigraph/src/paths/floyd_warshall.c
index 6ba9736875f..14be5979a5b 100644
--- a/src/vendor/cigraph/src/paths/floyd_warshall.c
+++ b/src/vendor/cigraph/src/paths/floyd_warshall.c
@@ -237,6 +237,7 @@ static igraph_error_t igraph_distances_floyd_warshall_tree(
* \param to The target vertices.
* \param weights The edge weights. If \c NULL, all weights are assumed to be 1.
* Negative weights are allowed, but the graph must not contain negative cycles.
+ * Edges with positive infinite weights are ignored.
* \param mode The type of shortest paths to be use for the
* calculation in directed graphs. Possible values:
* \clist
@@ -329,6 +330,9 @@ igraph_error_t igraph_distances_floyd_warshall(
"while calculating distances with Floyd-Warshall.",
IGRAPH_ENEGLOOP, w);
}
+ } else if (w == IGRAPH_INFINITY) {
+ /* Ignore edges with infinite weight */
+ continue;
}
if (out && MATRIX(*res, from, to) > w) {
diff --git a/src/vendor/cigraph/src/paths/johnson.c b/src/vendor/cigraph/src/paths/johnson.c
index 8ed7bd059e0..fdd09ffc8a0 100644
--- a/src/vendor/cigraph/src/paths/johnson.c
+++ b/src/vendor/cigraph/src/paths/johnson.c
@@ -66,7 +66,7 @@
* vertex twice or more.
* \param weights Optional edge weights. If it is a null-pointer, then
* the unweighted breadth-first search based \ref igraph_distances() will
- * be called.
+ * be called. Edges with positive infinite weights are ignored.
* \return Error code.
*
* Time complexity: O(s|V|log|V|+|V||E|), |V| and |E| are the number
diff --git a/src/vendor/cigraph/src/paths/random_walk.c b/src/vendor/cigraph/src/paths/random_walk.c
index f4cee7f9a67..60556b4e170 100644
--- a/src/vendor/cigraph/src/paths/random_walk.c
+++ b/src/vendor/cigraph/src/paths/random_walk.c
@@ -192,9 +192,7 @@ static igraph_error_t igraph_i_random_walk_inclist(
igraph_integer_t j;
*cd = IGRAPH_CALLOC(1, igraph_vector_t);
- if (*cd == NULL) {
- IGRAPH_ERROR("Random walk failed.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
- }
+ IGRAPH_CHECK_OOM(*cd, "Insufficient memory for random walk.");
IGRAPH_CHECK(igraph_vector_init(*cd, degree));
IGRAPH_CHECK(igraph_vector_resize(&weight_temp, degree));
diff --git a/src/vendor/cigraph/src/paths/shortest_paths.c b/src/vendor/cigraph/src/paths/shortest_paths.c
index e53b02706ed..29ad1dbee02 100644
--- a/src/vendor/cigraph/src/paths/shortest_paths.c
+++ b/src/vendor/cigraph/src/paths/shortest_paths.c
@@ -240,7 +240,9 @@ static igraph_error_t igraph_i_average_path_length_dijkstra(
igraph_bool_t active = igraph_2wheap_has_active(&Q, tto);
igraph_bool_t has = igraph_2wheap_has_elem(&Q, tto);
igraph_real_t curdist = active ? -igraph_2wheap_get(&Q, tto) : 0.0;
- if (!has) {
+ if (altdist == IGRAPH_INFINITY) {
+ /* Ignore edges with positive infinite weight */
+ } else if (!has) {
/* This is the first non-infinite distance */
IGRAPH_CHECK(igraph_2wheap_push_with_index(&Q, tto, -altdist));
} else if (altdist < curdist) {
@@ -342,7 +344,8 @@ igraph_error_t igraph_average_path_length(const igraph_t *graph,
* non-negative for Dijkstra's algorithm to work. Additionally, no
* edge weight may be NaN. If either case does not hold, an error
* is returned. If this is a null pointer, then the unweighted
- * version, \ref igraph_average_path_length() is called.
+ * version, \ref igraph_average_path_length() is called. Edges with positive
+ * infinite weight are ignored.
* \param directed Boolean, whether to consider directed paths.
* Ignored for undirected graphs.
* \param unconn If \c true, only those pairs are considered for the calculation
@@ -399,7 +402,8 @@ igraph_error_t igraph_average_path_length_dijkstra(const igraph_t *graph,
* edge weight may be NaN. If either case does not hold, an error
* is returned. If this is a null pointer, then the unweighted
* version, \ref igraph_average_path_length() is used in calculating
- * the global efficiency.
+ * the global efficiency. Edges with positive infinite weights are
+ * ignored.
* \param directed Boolean, whether to consider directed paths.
* Ignored for undirected graphs.
* \return Error code:
@@ -674,7 +678,8 @@ static igraph_error_t igraph_i_local_efficiency_dijkstra(
* non-negative. Additionally, no edge weight may be NaN. If either
* case does not hold, an error is returned. If this is a null
* pointer, then the unweighted version,
- * \ref igraph_average_path_length() is called.
+ * \ref igraph_average_path_length() is called. Edges with positive
+ * infinite weights are ignored.
* \param directed Boolean, whether to consider directed paths.
* Ignored for undirected graphs.
* \param mode How to determine the local neighborhood of each vertex
@@ -828,7 +833,8 @@ igraph_error_t igraph_local_efficiency(const igraph_t *graph, igraph_vector_t *r
* \param graph The graph object.
* \param res Pointer to a real number, this will contain the result.
* \param weights The edge weights. They must be all non-negative.
- * If a null pointer is given, all weights are assumed to be 1.
+ * If a null pointer is given, all weights are assumed to be 1. Edges
+ * with positive infinite weight are ignored.
* \param directed Boolean, whether to consider directed paths.
* Ignored for undirected graphs.
* \param mode How to determine the local neighborhood of each vertex
@@ -1073,7 +1079,7 @@ igraph_error_t igraph_diameter(const igraph_t *graph, igraph_real_t *res,
*
* \param graph The input graph, can be directed or undirected.
* \param weights The edge weights of the graph. Can be \c NULL for an
- * unweighted graph.
+ * unweighted graph. Edges with positive infinite weight are ignored.
* \param res Pointer to a real number, if not \c NULL then it will contain
* the diameter (the actual distance).
* \param from Pointer to an integer, if not \c NULL it will be set to the
diff --git a/src/vendor/cigraph/src/paths/simple_paths.c b/src/vendor/cigraph/src/paths/simple_paths.c
index 056216aa829..b8a7998357c 100644
--- a/src/vendor/cigraph/src/paths/simple_paths.c
+++ b/src/vendor/cigraph/src/paths/simple_paths.c
@@ -69,7 +69,8 @@ igraph_error_t igraph_get_all_simple_paths(const igraph_t *graph,
igraph_vit_t vit;
igraph_bool_t toall = igraph_vs_is_all(&to);
igraph_lazy_adjlist_t adjlist;
- igraph_vector_int_t stack, dist;
+ igraph_vector_int_t stack, dist; /* used as a stack, but represented as a vector,
+ in order to be appendable to other vectors */
igraph_vector_bool_t markto, added;
igraph_vector_int_t nptr;
int iteration = 0;
diff --git a/src/vendor/cigraph/src/paths/widest_paths.c b/src/vendor/cigraph/src/paths/widest_paths.c
index b76af01effe..b2c946d0102 100644
--- a/src/vendor/cigraph/src/paths/widest_paths.c
+++ b/src/vendor/cigraph/src/paths/widest_paths.c
@@ -55,7 +55,7 @@
* times.
* \param weights The edge weights. Edge weights can be negative. If this
* is a null pointer or if any edge weight is NaN, then an error
- * is returned.
+ * is returned. Edges with positive infinite weight are ignored.
* \param mode The type of widest paths to be used for the
* calculation in directed graphs. Possible values:
* \clist
@@ -217,7 +217,9 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph,
igraph_real_t edgewidth = VECTOR(*weights)[edge];
igraph_real_t altwidth = maxwidth < edgewidth ? maxwidth : edgewidth;
igraph_real_t curwidth = VECTOR(widths)[tto];
- if (curwidth < 0) {
+ if (edgewidth == IGRAPH_INFINITY) {
+ /* Ignore edges with infinite weight */
+ } else if (curwidth < 0) {
/* This is the first assigning a width to this vertex */
VECTOR(widths)[tto] = altwidth;
parent_eids[tto] = edge + 1;
@@ -348,7 +350,7 @@ igraph_error_t igraph_get_widest_paths(const igraph_t *graph,
* \param to The id of the target vertex.
* \param weights The edge weights. Edge weights can be negative. If this
* is a null pointer or if any edge weight is NaN, then an error
- * is returned.
+ * is returned. Edges with positive infinite weight are ignored.
* \param mode A constant specifying how edge directions are
* considered in directed graphs. \c IGRAPH_OUT follows edge
* directions, \c IGRAPH_IN follows the opposite directions,
@@ -432,7 +434,7 @@ igraph_error_t igraph_get_widest_path(const igraph_t *graph,
* \param to The target vertices.
* \param weights The edge weights. Edge weights can be negative. If this
* is a null pointer or if any edge weight is NaN, then an error
- * is returned.
+ * is returned. Edges with positive infinite weight are ignored.
* \param mode For directed graphs; whether to follow paths along edge
* directions (\c IGRAPH_OUT), or the opposite (\c IGRAPH_IN), or
* ignore edge directions completely (\c IGRAPH_ALL). It is ignored
@@ -510,6 +512,11 @@ igraph_error_t igraph_widest_path_widths_floyd_warshall(const igraph_t *graph,
igraph_integer_t to = IGRAPH_TO(graph, edge);
igraph_real_t w = VECTOR(*weights)[edge];
+ if (w == IGRAPH_INFINITY) {
+ /* Ignore edges with infinite weight */
+ continue;
+ }
+
if (out && MATRIX(*res, from, to) < w) MATRIX(*res, from, to) = w;
if (in && MATRIX(*res, to, from) < w) MATRIX(*res, to, from) = w;
}
@@ -568,7 +575,7 @@ igraph_error_t igraph_widest_path_widths_floyd_warshall(const igraph_t *graph,
* vertex twice or more.
* \param weights The edge weights. Edge weights can be negative. If this
* is a null pointer or if any edge weight is NaN, then an error
- * is returned.
+ * is returned. Edges with positive infinite weight are ignored.
* \param mode For directed graphs; whether to follow paths along edge
* directions (\c IGRAPH_OUT), or the opposite (\c IGRAPH_IN), or
* ignore edge directions completely (\c IGRAPH_ALL). It is ignored
@@ -699,7 +706,9 @@ igraph_error_t igraph_widest_path_widths_dijkstra(const igraph_t *graph,
igraph_bool_t active = igraph_2wheap_has_active(&Q, tto);
igraph_bool_t has = igraph_2wheap_has_elem(&Q, tto);
igraph_real_t curwidth = active ? igraph_2wheap_get(&Q, tto) : IGRAPH_POSINFINITY;
- if (!has) {
+ if (edgewidth == IGRAPH_INFINITY) {
+ /* Ignore edges with infinite weight */
+ } else if (!has) {
/* This is the first time assigning a width to this vertex */
IGRAPH_CHECK(igraph_2wheap_push_with_index(&Q, tto, altwidth));
} else if (altwidth > curwidth) {
diff --git a/src/vendor/cigraph/src/random/random.c b/src/vendor/cigraph/src/random/random.c
index a37495e8042..15ef86e12c6 100644
--- a/src/vendor/cigraph/src/random/random.c
+++ b/src/vendor/cigraph/src/random/random.c
@@ -1072,7 +1072,7 @@ static void igraph_i_random_sample_alga_real(igraph_vector_t *res,
* \brief Generates an increasing random sequence of integers (igraph_real_t version).
*
* This function is the 'real' version of \ref igraph_random_sample(), and was added
- * so \ref igraph_erdos_renyi_game() and related function can use a random sample
+ * so \ref igraph_erdos_renyi_game_gnm() and related functions can use a random sample
* of doubles instead of integers to prevent overflows on systems with 32-bit
* \type igraph_integer_t.
*
@@ -1096,7 +1096,7 @@ static void igraph_i_random_sample_alga_real(igraph_vector_t *res,
igraph_error_t igraph_random_sample_real(igraph_vector_t *res, igraph_real_t l,
igraph_real_t h, igraph_integer_t length) {
/* This function is the 'real' version of igraph_random_sample, and was added
- * so erdos_renyi_game can use a random sample of doubles instead of integers
+ * so erdos_renyi_game_gnm can use a random sample of doubles instead of integers
* to prevent overflows on systems with 32-bits igraph_integer_t.
*/
igraph_real_t N = h - l + 1;
diff --git a/src/vendor/cigraph/vendor/glpk/minisat/minisat.h b/src/vendor/cigraph/vendor/glpk/minisat/minisat.h
index 2733e8d63cd..5d6bb955ca1 100644
--- a/src/vendor/cigraph/vendor/glpk/minisat/minisat.h
+++ b/src/vendor/cigraph/vendor/glpk/minisat/minisat.h
@@ -34,10 +34,15 @@
/*====================================================================*/
/* Simple types: */
+/* Changed in igraph: do not try to redefine the standard 'bool',
+ * needed for C23 compatibility. */
+/*
typedef int bool;
#define true 1
#define false 0
+*/
+#include
typedef int lit;
#if 0 /* by mao */