@@ -13748,6 +13748,149 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self,
1374813748 return error ? NULL : Py_BuildValue("Nd", res, (double) quality);
1374913749}
1375013750
13751+ /**
13752+ * Voronoi clustering
13753+ */
13754+ PyObject *igraphmodule_Graph_community_voronoi(igraphmodule_GraphObject *self,
13755+ PyObject *args, PyObject *kwds) {
13756+ static char *kwlist[] = {"modularity", "lengths", "weights", "mode", "radius", NULL};
13757+ PyObject *lengths_o = Py_None, *weights_o = Py_None;
13758+ PyObject *mode_o = Py_None;
13759+ PyObject *radius_o = Py_None;
13760+ PyObject *modularity_o = Py_None;
13761+ igraph_vector_t *lengths_v = NULL;
13762+ igraph_vector_t *weights_v = NULL;
13763+ igraph_vector_int_t membership_v, generators_v;
13764+ igraph_neimode_t mode = IGRAPH_ALL;
13765+ igraph_real_t radius = -1.0; /* negative means auto-optimize */
13766+ igraph_real_t modularity = IGRAPH_NAN;
13767+ PyObject *membership_o, *generators_o, *result_o;
13768+ igraph_bool_t return_modularity = false;
13769+
13770+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist,
13771+ &modularity_o, &lengths_o, &weights_o, &mode_o, &radius_o))
13772+ return NULL;
13773+
13774+ if (modularity_o != Py_None){
13775+ modularity = (igraph_real_t)PyFloat_AsDouble(modularity_o);
13776+ }
13777+ else {
13778+ return_modularity = true;
13779+ }
13780+
13781+ /* Handle mode parameter */
13782+ if (mode_o != Py_None) {
13783+ if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode))
13784+ return NULL;
13785+ }
13786+
13787+ /* Handle radius parameter */
13788+ if (radius_o != Py_None) {
13789+ if (PyFloat_Check(radius_o)) {
13790+ radius = PyFloat_AsDouble(radius_o);
13791+ } else if (PyLong_Check(radius_o)) {
13792+ radius = PyLong_AsDouble(radius_o);
13793+ } else {
13794+ PyErr_SetString(PyExc_TypeError, "radius must be a number or None");
13795+ return NULL;
13796+ }
13797+ if (PyErr_Occurred()) return NULL;
13798+ }
13799+
13800+ /* Handle lengths parameter */
13801+ if (lengths_o != Py_None) {
13802+ if (igraphmodule_attrib_to_vector_t(lengths_o, self, &lengths_v, ATTRIBUTE_TYPE_EDGE)) {
13803+ return NULL;
13804+ }
13805+ }
13806+
13807+ /* Handle weights parameter */
13808+ if (weights_o != Py_None) {
13809+ if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights_v, ATTRIBUTE_TYPE_EDGE)) {
13810+ if (lengths_v != 0) {
13811+ igraph_vector_destroy(lengths_v); free(lengths_v);
13812+ }
13813+ return NULL;
13814+ }
13815+ }
13816+
13817+ /* Initialize result vectors */
13818+ if (igraph_vector_int_init(&membership_v, 0)) {
13819+ if (lengths_v != 0) {
13820+ igraph_vector_destroy(lengths_v); free(lengths_v);
13821+ }
13822+ if (weights_v != 0) {
13823+ igraph_vector_destroy(weights_v); free(weights_v);
13824+ }
13825+ igraphmodule_handle_igraph_error();
13826+ return NULL;
13827+ }
13828+
13829+ if (igraph_vector_int_init(&generators_v, 0)) {
13830+ if (lengths_v != 0) {
13831+ igraph_vector_destroy(lengths_v); free(lengths_v);
13832+ }
13833+ if (weights_v != 0) {
13834+ igraph_vector_destroy(weights_v); free(weights_v);
13835+ }
13836+ igraph_vector_int_destroy(&membership_v);
13837+ igraphmodule_handle_igraph_error();
13838+ return NULL;
13839+ }
13840+
13841+ /* Call the C function - pass NULL for None parameters */
13842+ if (igraph_community_voronoi(&self->g, &membership_v, &generators_v,
13843+ return_modularity ? &modularity : NULL,
13844+ lengths_v,
13845+ weights_v,
13846+ mode, radius)) {
13847+
13848+ if (lengths_v != 0) {
13849+ igraph_vector_destroy(lengths_v); free(lengths_v);
13850+ }
13851+ if (weights_v != 0) {
13852+ igraph_vector_destroy(weights_v); free(weights_v);
13853+ }
13854+ igraph_vector_int_destroy(&membership_v);
13855+ igraph_vector_int_destroy(&generators_v);
13856+ igraphmodule_handle_igraph_error();
13857+ return NULL;
13858+ }
13859+
13860+ /* Clean up input vectors */
13861+
13862+ if (lengths_v != 0) {
13863+ igraph_vector_destroy(lengths_v); free(lengths_v);
13864+ }
13865+ if (weights_v != 0) {
13866+ igraph_vector_destroy(weights_v); free(weights_v);
13867+ }
13868+
13869+ /* Convert results to Python objects */
13870+ membership_o = igraphmodule_vector_int_t_to_PyList(&membership_v);
13871+ igraph_vector_int_destroy(&membership_v);
13872+ if (!membership_o) {
13873+ igraph_vector_int_destroy(&generators_v);
13874+ return NULL;
13875+ }
13876+
13877+ generators_o = igraphmodule_vector_int_t_to_PyList(&generators_v);
13878+ igraph_vector_int_destroy(&generators_v);
13879+ if (!generators_o) {
13880+ Py_DECREF(membership_o);
13881+ return NULL;
13882+ }
13883+
13884+ /* Return tuple with membership, generators, and modularity */
13885+ if (return_modularity) {
13886+ result_o = Py_BuildValue("(NNd)", membership_o, generators_o, modularity);
13887+ } else {
13888+ result_o = Py_BuildValue("(NN)", membership_o, generators_o);
13889+ }
13890+
13891+ return result_o;
13892+ }
13893+
1375113894/**********************************************************************
1375213895 * Random walks *
1375313896 **********************************************************************/
@@ -13896,153 +14039,6 @@ PyObject *igraphmodule_Graph_random_walk(igraphmodule_GraphObject * self,
1389614039}
1389714040
1389814041
13899- /**********************************************************************
13900- * Other methods *
13901- **********************************************************************/
13902-
13903- /**
13904- * Voronoi clustering
13905- */
13906- PyObject *igraphmodule_Graph_community_voronoi(igraphmodule_GraphObject *self,
13907- PyObject *args, PyObject *kwds) {
13908- static char *kwlist[] = {"modularity", "lengths", "weights", "mode", "radius", NULL};
13909- PyObject *lengths_o = Py_None, *weights_o = Py_None;
13910- PyObject *mode_o = Py_None;
13911- PyObject *radius_o = Py_None;
13912- PyObject *modularity_o = Py_None;
13913- igraph_vector_t *lengths_v = NULL;
13914- igraph_vector_t *weights_v = NULL;
13915- igraph_vector_int_t membership_v, generators_v;
13916- igraph_neimode_t mode = IGRAPH_ALL;
13917- igraph_real_t radius = -1.0; /* negative means auto-optimize */
13918- igraph_real_t modularity = IGRAPH_NAN;
13919- PyObject *membership_o, *generators_o, *result_o;
13920- igraph_bool_t return_modularity = false;
13921-
13922- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist,
13923- &modularity_o, &lengths_o, &weights_o, &mode_o, &radius_o))
13924- return NULL;
13925-
13926- if (modularity_o != Py_None){
13927- modularity = (igraph_real_t)PyFloat_AsDouble(modularity_o);
13928- }
13929- else {
13930- return_modularity = true;
13931- }
13932-
13933- /* Handle mode parameter */
13934- if (mode_o != Py_None) {
13935- if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode))
13936- return NULL;
13937- }
13938-
13939- /* Handle radius parameter */
13940- if (radius_o != Py_None) {
13941- if (PyFloat_Check(radius_o)) {
13942- radius = PyFloat_AsDouble(radius_o);
13943- } else if (PyLong_Check(radius_o)) {
13944- radius = PyLong_AsDouble(radius_o);
13945- } else {
13946- PyErr_SetString(PyExc_TypeError, "radius must be a number or None");
13947- return NULL;
13948- }
13949- if (PyErr_Occurred()) return NULL;
13950- }
13951-
13952- /* Handle lengths parameter */
13953- if (lengths_o != Py_None) {
13954- if (igraphmodule_attrib_to_vector_t(lengths_o, self, &lengths_v, ATTRIBUTE_TYPE_EDGE)) {
13955- return NULL;
13956- }
13957- }
13958-
13959- /* Handle weights parameter */
13960- if (weights_o != Py_None) {
13961- if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights_v, ATTRIBUTE_TYPE_EDGE)) {
13962- if (lengths_v != 0) {
13963- igraph_vector_destroy(lengths_v); free(lengths_v);
13964- }
13965- return NULL;
13966- }
13967- }
13968-
13969- /* Initialize result vectors */
13970- if (igraph_vector_int_init(&membership_v, 0)) {
13971- if (lengths_v != 0) {
13972- igraph_vector_destroy(lengths_v); free(lengths_v);
13973- }
13974- if (weights_v != 0) {
13975- igraph_vector_destroy(weights_v); free(weights_v);
13976- }
13977- igraphmodule_handle_igraph_error();
13978- return NULL;
13979- }
13980-
13981- if (igraph_vector_int_init(&generators_v, 0)) {
13982- if (lengths_v != 0) {
13983- igraph_vector_destroy(lengths_v); free(lengths_v);
13984- }
13985- if (weights_v != 0) {
13986- igraph_vector_destroy(weights_v); free(weights_v);
13987- }
13988- igraph_vector_int_destroy(&membership_v);
13989- igraphmodule_handle_igraph_error();
13990- return NULL;
13991- }
13992-
13993- /* Call the C function - pass NULL for None parameters */
13994- if (igraph_community_voronoi(&self->g, &membership_v, &generators_v,
13995- return_modularity ? &modularity : NULL,
13996- lengths_v,
13997- weights_v,
13998- mode, radius)) {
13999-
14000- if (lengths_v != 0) {
14001- igraph_vector_destroy(lengths_v); free(lengths_v);
14002- }
14003- if (weights_v != 0) {
14004- igraph_vector_destroy(weights_v); free(weights_v);
14005- }
14006- igraph_vector_int_destroy(&membership_v);
14007- igraph_vector_int_destroy(&generators_v);
14008- igraphmodule_handle_igraph_error();
14009- return NULL;
14010- }
14011-
14012- /* Clean up input vectors */
14013-
14014- if (lengths_v != 0) {
14015- igraph_vector_destroy(lengths_v); free(lengths_v);
14016- }
14017- if (weights_v != 0) {
14018- igraph_vector_destroy(weights_v); free(weights_v);
14019- }
14020-
14021- /* Convert results to Python objects */
14022- membership_o = igraphmodule_vector_int_t_to_PyList(&membership_v);
14023- igraph_vector_int_destroy(&membership_v);
14024- if (!membership_o) {
14025- igraph_vector_int_destroy(&generators_v);
14026- return NULL;
14027- }
14028-
14029- generators_o = igraphmodule_vector_int_t_to_PyList(&generators_v);
14030- igraph_vector_int_destroy(&generators_v);
14031- if (!generators_o) {
14032- Py_DECREF(membership_o);
14033- return NULL;
14034- }
14035-
14036- /* Return tuple with membership, generators, and modularity */
14037- if (return_modularity) {
14038- result_o = Py_BuildValue("(NNd)", membership_o, generators_o, modularity);
14039- } else {
14040- result_o = Py_BuildValue("(NN)", membership_o, generators_o);
14041- }
14042-
14043- return result_o;
14044- }
14045-
1404614042/**********************************************************************
1404714043 * Special internal methods that you won't need to mess around with *
1404814044 **********************************************************************/
0 commit comments