diff --git a/R/aaa-auto.R b/R/aaa-auto.R
index 1ff5d31d69..a04fa1f187 100644
--- a/R/aaa-auto.R
+++ b/R/aaa-auto.R
@@ -3580,15 +3580,16 @@ find_cycle_impl <- function(graph, mode=c("out", "in", "all", "total")) {
res
}
-simple_cycles_impl <- function(graph, mode=c("out", "in", "all", "total"), max.cycle.length=-1) {
+simple_cycles_impl <- function(graph, mode=c("out", "in", "all", "total"), min.cycle.length=-1, max.cycle.length=-1) {
# Argument checks
ensure_igraph(graph)
mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L)
+ min.cycle.length <- as.numeric(min.cycle.length)
max.cycle.length <- as.numeric(max.cycle.length)
on.exit( .Call(R_igraph_finalizer) )
# Function call
- res <- .Call(R_igraph_simple_cycles, graph, mode, max.cycle.length)
+ res <- .Call(R_igraph_simple_cycles, graph, mode, min.cycle.length, max.cycle.length)
if (igraph_opt("return.vs.es")) {
res$vertices <- lapply(res$vertices, unsafe_create_vs, graph = graph, verts = V(graph))
}
diff --git a/src/cpp11.cpp b/src/cpp11.cpp
index db2c70976e..f5181f421d 100644
--- a/src/cpp11.cpp
+++ b/src/cpp11.cpp
@@ -401,7 +401,7 @@ extern SEXP R_igraph_similarity_inverse_log_weighted(SEXP, SEXP, SEXP);
extern SEXP R_igraph_similarity_jaccard(SEXP, SEXP, SEXP, SEXP);
extern SEXP R_igraph_similarity_jaccard_es(SEXP, SEXP, SEXP, SEXP);
extern SEXP R_igraph_similarity_jaccard_pairs(SEXP, SEXP, SEXP, SEXP);
-extern SEXP R_igraph_simple_cycles(SEXP, SEXP, SEXP);
+extern SEXP R_igraph_simple_cycles(SEXP, SEXP, SEXP, SEXP);
extern SEXP R_igraph_simple_interconnected_islands_game(SEXP, SEXP, SEXP, SEXP);
extern SEXP R_igraph_simplify(SEXP, SEXP, SEXP, SEXP);
extern SEXP R_igraph_simplify_and_colorize(SEXP);
@@ -856,7 +856,7 @@ static const R_CallMethodDef CallEntries[] = {
{"R_igraph_similarity_jaccard", (DL_FUNC) &R_igraph_similarity_jaccard, 4},
{"R_igraph_similarity_jaccard_es", (DL_FUNC) &R_igraph_similarity_jaccard_es, 4},
{"R_igraph_similarity_jaccard_pairs", (DL_FUNC) &R_igraph_similarity_jaccard_pairs, 4},
- {"R_igraph_simple_cycles", (DL_FUNC) &R_igraph_simple_cycles, 3},
+ {"R_igraph_simple_cycles", (DL_FUNC) &R_igraph_simple_cycles, 4},
{"R_igraph_simple_interconnected_islands_game", (DL_FUNC) &R_igraph_simple_interconnected_islands_game, 4},
{"R_igraph_simplify", (DL_FUNC) &R_igraph_simplify, 4},
{"R_igraph_simplify_and_colorize", (DL_FUNC) &R_igraph_simplify_and_colorize, 1},
diff --git a/src/rinterface.c b/src/rinterface.c
index bec61580ac..0374a61fee 100644
--- a/src/rinterface.c
+++ b/src/rinterface.c
@@ -10968,12 +10968,13 @@ SEXP R_igraph_find_cycle(SEXP graph, SEXP mode) {
/*-------------------------------------------/
/ igraph_simple_cycles /
/-------------------------------------------*/
-SEXP R_igraph_simple_cycles(SEXP graph, SEXP mode, SEXP max_cycle_length) {
+SEXP R_igraph_simple_cycles(SEXP graph, SEXP mode, SEXP min_cycle_length, SEXP max_cycle_length) {
/* Declarations */
igraph_t c_graph;
igraph_vector_int_list_t c_vertices;
igraph_vector_int_list_t c_edges;
igraph_neimode_t c_mode;
+ igraph_integer_t c_min_cycle_length;
igraph_integer_t c_max_cycle_length;
SEXP vertices;
SEXP edges;
@@ -10986,10 +10987,12 @@ SEXP R_igraph_simple_cycles(SEXP graph, SEXP mode, SEXP max_cycle_length) {
IGRAPH_R_CHECK(igraph_vector_int_list_init(&c_edges, 0));
IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_edges);
c_mode = (igraph_neimode_t) Rf_asInteger(mode);
+ IGRAPH_R_CHECK_INT(min_cycle_length);
+ c_min_cycle_length = (igraph_integer_t) REAL(min_cycle_length)[0];
IGRAPH_R_CHECK_INT(max_cycle_length);
c_max_cycle_length = (igraph_integer_t) REAL(max_cycle_length)[0];
/* Call igraph */
- IGRAPH_R_CHECK(igraph_simple_cycles(&c_graph, &c_vertices, &c_edges, c_mode, c_max_cycle_length));
+ IGRAPH_R_CHECK(igraph_simple_cycles(&c_graph, &c_vertices, &c_edges, c_mode, c_min_cycle_length, c_max_cycle_length));
/* Convert output */
PROTECT(r_result=NEW_LIST(2));
diff --git a/src/vendor/cigraph/.all-contributorsrc b/src/vendor/cigraph/.all-contributorsrc
index e031cc7cc4..65201c5342 100644
--- a/src/vendor/cigraph/.all-contributorsrc
+++ b/src/vendor/cigraph/.all-contributorsrc
@@ -594,6 +594,24 @@
"contributions": [
"code"
]
+ },
+ {
+ "login": "GenieTim",
+ "name": "Tim Bernhard",
+ "avatar_url": "https://avatars.githubusercontent.com/u/8596965?v=4",
+ "profile": "https://github.com/GenieTim",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "maelle",
+ "name": "Maëlle Salmon",
+ "avatar_url": "https://avatars.githubusercontent.com/u/8360597?v=4",
+ "profile": "https://masalmon.eu/",
+ "contributions": [
+ "code"
+ ]
}
],
"contributorsPerLine": 7
diff --git a/src/vendor/cigraph/CHANGELOG.md b/src/vendor/cigraph/CHANGELOG.md
index b8fe2d4c52..4130bc79cd 100644
--- a/src/vendor/cigraph/CHANGELOG.md
+++ b/src/vendor/cigraph/CHANGELOG.md
@@ -2,6 +2,8 @@
## [master]
+## [0.10.15]
+
### Added
- `igraph_bitset_update()` copies the contents of one bitset into another (experimental function).
@@ -1445,7 +1447,8 @@ Some of the highlights are:
- Provide proper support for Windows, using `__declspec(dllexport)` and `__declspec(dllimport)` for `DLL`s and static usage by using `#define IGRAPH_STATIC 1`.
- Provided integer versions of `dqueue` and `stack` data types.
-[master]: https://github.com/igraph/igraph/compare/0.10.13..master
+[master]: https://github.com/igraph/igraph/compare/0.10.15..master
+[0.10.15]: https://github.com/igraph/igraph/compare/0.10.13..0.10.15
[0.10.13]: https://github.com/igraph/igraph/compare/0.10.12..0.10.13
[0.10.12]: https://github.com/igraph/igraph/compare/0.10.11..0.10.12
[0.10.11]: https://github.com/igraph/igraph/compare/0.10.10..0.10.11
diff --git a/src/vendor/cigraph/CONTRIBUTORS.md b/src/vendor/cigraph/CONTRIBUTORS.md
index 3d2f470665..349ec3150e 100644
--- a/src/vendor/cigraph/CONTRIBUTORS.md
+++ b/src/vendor/cigraph/CONTRIBUTORS.md
@@ -6,91 +6,95 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
diff --git a/src/vendor/cigraph/CONTRIBUTORS.txt b/src/vendor/cigraph/CONTRIBUTORS.txt
index 92702f357d..826271e153 100644
--- a/src/vendor/cigraph/CONTRIBUTORS.txt
+++ b/src/vendor/cigraph/CONTRIBUTORS.txt
@@ -65,6 +65,8 @@ Arnar Bjarni Arnarson (@Tagl)
David Seifert (@SoapGentoo)
Kirill Müller (@krlmlr)
Michael (@gendelpiekel)
+Tim Bernhard (@GenieTim)
+Maëlle Salmon (@maelle)
This project follows the [all-contributors][1] specification. Contributions of any kind welcome!
diff --git a/src/vendor/cigraph/include/igraph_cycles.h b/src/vendor/cigraph/include/igraph_cycles.h
index 060ed4f77f..2f38aa8d14 100644
--- a/src/vendor/cigraph/include/igraph_cycles.h
+++ b/src/vendor/cigraph/include/igraph_cycles.h
@@ -71,13 +71,18 @@ typedef igraph_error_t igraph_cycle_handler_t(
IGRAPH_EXPORT igraph_error_t igraph_simple_cycles_callback(
const igraph_t *graph,
- igraph_neimode_t mode, igraph_integer_t max_cycle_length,
+ igraph_neimode_t mode,
+ igraph_integer_t min_cycle_length,
+ igraph_integer_t max_cycle_length,
igraph_cycle_handler_t *callback, void *arg);
IGRAPH_EXPORT igraph_error_t igraph_simple_cycles(
const igraph_t *graph,
- igraph_vector_int_list_t *vertices, igraph_vector_int_list_t *edges,
- igraph_neimode_t mode, igraph_integer_t max_cycle_length);
+ igraph_vector_int_list_t *vertices,
+ igraph_vector_int_list_t *edges,
+ igraph_neimode_t mode,
+ igraph_integer_t min_cycle_length,
+ igraph_integer_t max_cycle_length);
__END_DECLS
diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml
index 232608bb8b..e6e923e805 100644
--- a/src/vendor/cigraph/interfaces/functions.yaml
+++ b/src/vendor/cigraph/interfaces/functions.yaml
@@ -59,7 +59,7 @@ igraph_is_directed:
igraph_degree:
PARAMS: |-
GRAPH graph, OUT VECTOR_INT res, VERTEX_SELECTOR vids=ALL, NEIMODE mode=ALL,
- BOOLEAN loops
+ BOOLEAN loops=True
DEPS: vids ON graph
igraph_edge:
@@ -2542,13 +2542,13 @@ igraph_simple_cycles:
PARAMS: |-
GRAPH graph,
OPTIONAL OUT VERTEXSET_LIST vertices, OPTIONAL OUT EDGESET_LIST edges,
- NEIMODE mode=OUT, INTEGER max_cycle_length=-1
+ NEIMODE mode=OUT, INTEGER min_cycle_length=-1, INTEGER max_cycle_length=-1
DEPS: vertices ON graph, edges ON graph
igraph_simple_cycles_callback:
PARAMS: |-
GRAPH graph,
- NEIMODE mode=OUT, INTEGER max_cycle_length=-1,
+ NEIMODE mode=OUT, INTEGER min_cycle_length=-1, INTEGER max_cycle_length=-1,
CYCLE_FUNC cycle_handler, OPTIONAL EXTRA arg
#######################################
diff --git a/src/vendor/cigraph/src/CMakeLists.txt b/src/vendor/cigraph/src/CMakeLists.txt
index e59bc9200c..ac95f94179 100644
--- a/src/vendor/cigraph/src/CMakeLists.txt
+++ b/src/vendor/cigraph/src/CMakeLists.txt
@@ -332,7 +332,7 @@ add_library(
add_dependencies(igraph parsersources)
# Set soname for the library
-set_target_properties(igraph PROPERTIES VERSION "3.1.8")
+set_target_properties(igraph PROPERTIES VERSION "3.1.9")
set_target_properties(igraph PROPERTIES SOVERSION 3)
# Add extra compiler definitions if needed
diff --git a/src/vendor/cigraph/src/cycles/simple_cycles.c b/src/vendor/cigraph/src/cycles/simple_cycles.c
index 0c505e3f59..2b562951d2 100644
--- a/src/vendor/cigraph/src/cycles/simple_cycles.c
+++ b/src/vendor/cigraph/src/cycles/simple_cycles.c
@@ -134,10 +134,10 @@ static igraph_error_t igraph_i_simple_cycles_unblock(
* \param arg: argument to pass to the callback function
*/
static igraph_error_t igraph_i_simple_cycles_circuit(
- igraph_i_simple_cycle_search_state_t *state,
- igraph_integer_t V,
- igraph_cycle_handler_t *callback,
- igraph_integer_t max_cycle_length, void *arg) {
+ igraph_i_simple_cycle_search_state_t *state, igraph_integer_t V,
+ igraph_integer_t max_cycle_length,
+ igraph_integer_t min_cycle_length,
+ igraph_cycle_handler_t *callback, void *arg) {
const igraph_vector_int_t *neighbors;
const igraph_vector_int_t *incident_edges;
@@ -178,7 +178,7 @@ static igraph_error_t igraph_i_simple_cycles_circuit(
// printf("Pushing %" IGRAPH_PRId " to stack, stack size is %" IGRAPH_PRId
// ", result size is %" IGRAPH_PRId "\n",
// V, igraph_vector_int_size(&state->vertex_stack),
- // igraph_vector_int_list_size(vertices));
+ // igraph_stack_int_size(&v_stack));
VECTOR(state->v_blocked)[V] = true;
} else {
// back to what we were doing before
@@ -206,16 +206,17 @@ static igraph_error_t igraph_i_simple_cycles_circuit(
if ((!state->directed &&
igraph_vector_int_size(&state->edge_stack) == 1 &&
- igraph_vector_int_get(&state->edge_stack, 0) == WE)) {
- // printf("Skipping cycle to prevent self-loop: \n");
+ VECTOR(state->edge_stack)[0] == WE)) {
+ // printf("Skipping cycle to %" IGRAPH_PRId " via %" IGRAPH_PRId " to prevent self-loop.\n", W, WE);
continue;
}
// prevent duplicates in undirected graphs by forcing a direction for
// the closing edge
if ((!state->directed &&
- igraph_vector_int_get(&state->edge_stack, 0) > WE)) {
- // printf("Skipping cycle to prevent duplicates: \n");
+ igraph_vector_int_size(&state->edge_stack) > 0 &&
+ VECTOR(state->edge_stack)[0] > WE)) {
+ // printf("Skipping cycle to %" IGRAPH_PRId " via %" IGRAPH_PRId " to prevent duplicates.\n", W, WE);
continue;
}
@@ -225,16 +226,16 @@ static igraph_error_t igraph_i_simple_cycles_circuit(
// printf("Found cycle with size %" IGRAPH_PRId "\n",
// igraph_vector_int_size(&state->vertex_stack));
- IGRAPH_CHECK_CALLBACK(callback(&state->vertex_stack, &state->edge_stack, arg), &ret);
- if (ret == IGRAPH_STOP) {
- state->stop_search = true;
- break;
+ if (igraph_vector_int_size(&state->edge_stack) >= min_cycle_length) {
+ IGRAPH_CHECK_CALLBACK(callback(&state->vertex_stack, &state->edge_stack, arg), &ret);
+ if (ret == IGRAPH_STOP) {
+ state->stop_search = true;
+ break;
+ }
}
igraph_vector_int_pop_back(&state->edge_stack);
} else if (!(VECTOR(state->v_blocked)[W])) {
- // printf("Recursing deeper from %" IGRAPH_PRId " to %" IGRAPH_PRId
- // "\n",
- // V, W);
+ // printf("Recursing deeper from %" IGRAPH_PRId " to %" IGRAPH_PRId "\n", V, W);
recurse_deeper = ((max_cycle_length < 0) ||
(igraph_vector_int_size(&state->vertex_stack) <=
max_cycle_length - 1));
@@ -432,6 +433,7 @@ static igraph_error_t igraph_i_append_simple_cycle_result(
static igraph_error_t igraph_i_simple_cycles_search_callback_from_one_vertex(
igraph_i_simple_cycle_search_state_t *state,
igraph_integer_t s,
+ igraph_integer_t min_cycle_length,
igraph_integer_t max_cycle_length,
igraph_cycle_handler_t *callback,
void *arg) {
@@ -442,7 +444,9 @@ static igraph_error_t igraph_i_simple_cycles_search_callback_from_one_vertex(
igraph_vector_int_clear(igraph_adjlist_get(&state->B, i));
}
- IGRAPH_CHECK(igraph_i_simple_cycles_circuit(state, s, callback, max_cycle_length, arg));
+ IGRAPH_CHECK(igraph_i_simple_cycles_circuit(state, s,
+ max_cycle_length, min_cycle_length,
+ callback, arg));
for (igraph_integer_t i = 0; i < state->N; ++i) {
// We want to remove the vertex with value s, not at position s.
@@ -488,6 +492,8 @@ static igraph_error_t igraph_i_simple_cycles_search_callback_from_one_vertex(
* \c IGRAPH_IN, follows the opposite directions; and
* \c IGRAPH_ALL, ignores edge directions. This argument is
* ignored for undirected graphs.
+ * \param max_cycle_length Limit the minimum length of cycles to search for.
+ * Pass a negative value to search for all cycles.
* \param max_cycle_length Limit the maximum length of cycles to search for.
* Pass a negative value to search for all cycles.
* \param callback A function to call for each cycle that is found.
@@ -505,6 +511,7 @@ static igraph_error_t igraph_i_simple_cycles_search_callback_from_one_vertex(
igraph_error_t igraph_simple_cycles_callback(
const igraph_t *graph,
igraph_neimode_t mode,
+ igraph_integer_t min_cycle_length,
igraph_integer_t max_cycle_length,
igraph_cycle_handler_t *callback,
void *arg) {
@@ -523,7 +530,7 @@ igraph_error_t igraph_simple_cycles_callback(
for (igraph_integer_t i = 0; i < state.N; i++) {
if (!igraph_vector_int_empty(igraph_adjlist_get(&state.AK, i))) {
IGRAPH_CHECK(igraph_i_simple_cycles_search_callback_from_one_vertex(
- &state, i, max_cycle_length, callback, arg));
+ &state, i, min_cycle_length, max_cycle_length, callback, arg));
IGRAPH_ALLOW_INTERRUPTION();
}
if (state.stop_search) {
@@ -566,6 +573,8 @@ igraph_error_t igraph_simple_cycles_callback(
* \c IGRAPH_IN, follows the opposite directions; and
* \c IGRAPH_ALL, ignores edge directions. This argument is
* ignored for undirected graphs.
+ * \param max_cycle_length Limit the minimum length of cycles to search for.
+ * Pass a negative value to search for all cycles.
* \param max_cycle_length Limit the maximum length of cycles to search for.
* Pass a negative value to search for all cycles.
*
@@ -582,6 +591,7 @@ igraph_error_t igraph_simple_cycles(
igraph_vector_int_list_t *vertices,
igraph_vector_int_list_t *edges,
igraph_neimode_t mode,
+ igraph_integer_t min_cycle_length,
igraph_integer_t max_cycle_length) {
igraph_i_simple_cycle_results_t result_list;
@@ -595,7 +605,7 @@ igraph_error_t igraph_simple_cycles(
igraph_vector_int_list_clear(edges);
}
- igraph_simple_cycles_callback(graph, mode, max_cycle_length,
+ igraph_simple_cycles_callback(graph, mode, min_cycle_length, max_cycle_length,
&igraph_i_append_simple_cycle_result,
&result_list);
diff --git a/src/vendor/igraph_version.h b/src/vendor/igraph_version.h
index a1c72365ab..fea50a9275 100644
--- a/src/vendor/igraph_version.h
+++ b/src/vendor/igraph_version.h
@@ -28,11 +28,11 @@
__BEGIN_DECLS
-#define IGRAPH_VERSION "0.10.13-154-ga6441e7a0"
+#define IGRAPH_VERSION "0.10.15-1-ga16619502"
#define IGRAPH_VERSION_MAJOR 0
#define IGRAPH_VERSION_MINOR 10
-#define IGRAPH_VERSION_PATCH 13
-#define IGRAPH_VERSION_PRERELEASE "154-ga6441e7a0"
+#define IGRAPH_VERSION_PATCH 15
+#define IGRAPH_VERSION_PRERELEASE "1-ga16619502"
IGRAPH_EXPORT void igraph_version(const char **version_string,
int *major,