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 */