Skip to content

Commit 76dfe11

Browse files
committed
Merge remote-tracking branch 'upstream/develop' into feat/community-detection-guide-docs
2 parents ea6d5e8 + 42e7a53 commit 76dfe11

File tree

6 files changed

+59
-147
lines changed

6 files changed

+59
-147
lines changed

src/_igraph/convert.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ int igraphmodule_PyObject_to_eigen_which_t(PyObject *o,
374374
w->pos = IGRAPH_EIGEN_LM;
375375
w->howmany = 1;
376376
w->il = w->iu = -1;
377-
w->vl = IGRAPH_NEGINFINITY;
377+
w->vl = -IGRAPH_INFINITY;
378378
w->vu = IGRAPH_INFINITY;
379379
w->vestimate = 0;
380380
w->balance = IGRAPH_LAPACK_DGEEVX_BALANCE_NONE;

src/_igraph/graphobject.c

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#include "indexing.h"
3434
#include "memory.h"
3535
#include "pyhelpers.h"
36-
#include "utils.h"
3736
#include "vertexseqobject.h"
3837
#include <float.h>
3938

@@ -5571,14 +5570,14 @@ PyObject *igraphmodule_Graph_get_shortest_path(
55715570
return NULL;
55725571
}
55735572

5574-
if (algorithm == IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO) {
5575-
algorithm = igraphmodule_select_shortest_path_algorithm(
5576-
&self->g, weights, NULL, mode, /* allow_johnson = */ false
5577-
);
5578-
}
5579-
55805573
/* Call the C function */
55815574
switch (algorithm) {
5575+
case IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO:
5576+
retval = igraph_get_shortest_path(
5577+
&self->g, weights, use_edges ? NULL : &vec, use_edges ? &vec : NULL, from, to, mode
5578+
);
5579+
break;
5580+
55825581
case IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_DIJKSTRA:
55835582
retval = igraph_get_shortest_path_dijkstra(
55845583
&self->g, use_edges ? NULL : &vec, use_edges ? &vec : NULL, from, to, weights, mode
@@ -5793,14 +5792,15 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject *
57935792
return NULL;
57945793
}
57955794

5796-
if (algorithm == IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO) {
5797-
algorithm = igraphmodule_select_shortest_path_algorithm(
5798-
&self->g, weights, NULL, mode, /* allow_johnson = */ false
5799-
);
5800-
}
5801-
58025795
/* Call the C function */
58035796
switch (algorithm) {
5797+
case IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO:
5798+
retval = igraph_get_shortest_paths(
5799+
&self->g, weights, use_edges ? NULL : &veclist, use_edges ? &veclist : NULL,
5800+
from, to, mode, NULL, NULL
5801+
);
5802+
break;
5803+
58045804
case IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_DIJKSTRA:
58055805
retval = igraph_get_shortest_paths_dijkstra(
58065806
&self->g, use_edges ? NULL : &veclist, use_edges ? &veclist : NULL,
@@ -6619,14 +6619,12 @@ PyObject *igraphmodule_Graph_distances(
66196619
return igraphmodule_handle_igraph_error();
66206620
}
66216621

6622-
if (algorithm == IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO) {
6623-
algorithm = igraphmodule_select_shortest_path_algorithm(
6624-
&self->g, weights, &from_vs, mode, /* allow_johnson = */ true
6625-
);
6626-
}
6627-
66286622
/* Call the C function */
66296623
switch (algorithm) {
6624+
case IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO:
6625+
retval = igraph_distances(&self->g, weights, &res, from_vs, to_vs, mode);
6626+
break;
6627+
66306628
case IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_DIJKSTRA:
66316629
retval = igraph_distances_dijkstra(&self->g, &res, from_vs, to_vs, weights, mode);
66326630
break;
@@ -13611,11 +13609,12 @@ PyObject *igraphmodule_Graph_community_walktrap(igraphmodule_GraphObject * self,
1361113609
PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self,
1361213610
PyObject *args, PyObject *kwds) {
1361313611

13614-
static char *kwlist[] = {"edge_weights", "node_weights", "resolution",
13612+
static char *kwlist[] = {"edge_weights", "node_weights", "node_in_weights", "resolution",
1361513613
"normalize_resolution", "beta", "initial_membership", "n_iterations", NULL};
1361613614

1361713615
PyObject *edge_weights_o = Py_None;
1361813616
PyObject *node_weights_o = Py_None;
13617+
PyObject *node_in_weights_o = Py_None;
1361913618
PyObject *initial_membership_o = Py_None;
1362013619
PyObject *normalize_resolution = Py_False;
1362113620
PyObject *res = Py_None;
@@ -13624,14 +13623,14 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self,
1362413623
Py_ssize_t n_iterations = 2;
1362513624
double resolution = 1.0;
1362613625
double beta = 0.01;
13627-
igraph_vector_t *edge_weights = NULL, *node_weights = NULL;
13626+
igraph_vector_t *edge_weights = NULL, *node_weights = NULL, *node_in_weights = NULL;
1362813627
igraph_vector_int_t *membership = NULL;
1362913628
igraph_bool_t start = true;
1363013629
igraph_integer_t nb_clusters = 0;
1363113630
igraph_real_t quality = 0.0;
1363213631

13633-
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOdOdOn", kwlist,
13634-
&edge_weights_o, &node_weights_o, &resolution, &normalize_resolution, &beta, &initial_membership_o, &n_iterations))
13632+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOdOdOn", kwlist,
13633+
&edge_weights_o, &node_weights_o, &node_in_weights_o, &resolution, &normalize_resolution, &beta, &initial_membership_o, &n_iterations))
1363513634
return NULL;
1363613635

1363713636
if (n_iterations >= 0) {
@@ -13654,6 +13653,13 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self,
1365413653
error = -1;
1365513654
}
1365613655

13656+
/* Get node in-weights (directed case) */
13657+
if (!error && igraphmodule_attrib_to_vector_t(node_in_weights_o, self, &node_in_weights,
13658+
ATTRIBUTE_TYPE_VERTEX)) {
13659+
igraphmodule_handle_igraph_error();
13660+
error = -1;
13661+
}
13662+
1365713663
/* Get initial membership */
1365813664
if (!error && igraphmodule_attrib_to_vector_int_t(initial_membership_o, self, &membership,
1365913665
ATTRIBUTE_TYPE_VERTEX)) {
@@ -13664,30 +13670,35 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self,
1366413670
if (!error && membership == 0) {
1366513671
start = 0;
1366613672
membership = (igraph_vector_int_t*)calloc(1, sizeof(igraph_vector_int_t));
13667-
if (membership==0) {
13673+
if (membership == 0) {
1366813674
PyErr_NoMemory();
1366913675
error = -1;
13670-
} else {
13671-
igraph_vector_int_init(membership, 0);
13676+
} else if (igraph_vector_int_init(membership, 0)) {
13677+
igraphmodule_handle_igraph_error();
13678+
error = -1;
1367213679
}
1367313680
}
1367413681

13675-
if (PyObject_IsTrue(normalize_resolution))
13682+
if (!error && PyObject_IsTrue(normalize_resolution))
1367613683
{
1367713684
/* If we need to normalize the resolution parameter,
1367813685
* we will need to have node weights. */
1367913686
if (node_weights == 0)
1368013687
{
1368113688
node_weights = (igraph_vector_t*)calloc(1, sizeof(igraph_vector_t));
13682-
if (node_weights==0) {
13689+
if (node_weights == 0) {
1368313690
PyErr_NoMemory();
1368413691
error = -1;
13685-
} else {
13686-
igraph_vector_init(node_weights, 0);
13687-
if (igraph_strength(&self->g, node_weights, igraph_vss_all(), IGRAPH_ALL, 0, edge_weights)) {
13688-
igraphmodule_handle_igraph_error();
13689-
error = -1;
13690-
}
13692+
} else if (igraph_vector_init(node_weights, 0)) {
13693+
igraphmodule_handle_igraph_error();
13694+
error = -1;
13695+
} else if (igraph_strength(
13696+
&self->g, node_weights, igraph_vss_all(),
13697+
igraph_is_directed(&self->g) ? IGRAPH_OUT : IGRAPH_ALL,
13698+
IGRAPH_NO_LOOPS, edge_weights
13699+
)) {
13700+
igraphmodule_handle_igraph_error();
13701+
error = -1;
1369113702
}
1369213703
}
1369313704
resolution /= igraph_vector_sum(node_weights);
@@ -13696,7 +13707,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self,
1369613707
/* Run actual Leiden algorithm for several iterations. */
1369713708
if (!error) {
1369813709
error = igraph_community_leiden(&self->g,
13699-
edge_weights, node_weights,
13710+
edge_weights, node_weights, node_in_weights,
1370013711
resolution, beta,
1370113712
start, n_iterations, membership,
1370213713
&nb_clusters, &quality);
@@ -13710,6 +13721,10 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self,
1371013721
igraph_vector_destroy(node_weights);
1371113722
free(node_weights);
1371213723
}
13724+
if (node_in_weights != 0) {
13725+
igraph_vector_destroy(node_in_weights);
13726+
free(node_in_weights);
13727+
}
1371313728

1371413729
if (!error && membership != 0) {
1371513730
res = igraphmodule_vector_int_t_to_PyList(membership);

src/_igraph/utils.c

Lines changed: 0 additions & 70 deletions
This file was deleted.

src/_igraph/utils.h

Lines changed: 0 additions & 40 deletions
This file was deleted.

src/igraph/community.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ def _community_leiden(
461461
initial_membership=None,
462462
n_iterations=2,
463463
node_weights=None,
464+
node_in_weights=None,
464465
**kwds,
465466
):
466467
"""Finds the community structure of the graph using the Leiden
@@ -491,6 +492,11 @@ def _community_leiden(
491492
If this is not provided, it will be automatically determined on the
492493
basis of whether you want to use CPM or modularity. If you do provide
493494
this, please make sure that you understand what you are doing.
495+
@param node_in_weights: the inbound node weights used in the directed
496+
variant of the Leiden algorithm. If this is not provided, it will be
497+
automatically determined on the basis of whether you want to use CPM or
498+
modularity. If you do provide this, please make sure that you understand
499+
what you are doing.
494500
@return: an appropriate L{VertexClustering} object with an extra attribute
495501
called C{quality} that stores the value of the internal quality function
496502
optimized by the algorithm.
@@ -512,6 +518,7 @@ def _community_leiden(
512518
graph,
513519
edge_weights=weights,
514520
node_weights=node_weights,
521+
node_in_weights=node_in_weights,
515522
resolution=resolution,
516523
normalize_resolution=(objective_function == "modularity"),
517524
beta=beta,

vendor/source/igraph

Submodule igraph updated 109 files

0 commit comments

Comments
 (0)