From 82ae0208ca215c13047f92a96231456cf94149d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Sat, 17 Aug 2024 16:43:42 +0000 Subject: [PATCH] feat: feedback_vertex_set() --- src/_igraph/convert.c | 13 +++++++++ src/_igraph/convert.h | 1 + src/_igraph/graphobject.c | 59 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 3529d6921..a96bc514d 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -603,6 +603,19 @@ int igraphmodule_PyObject_to_fas_algorithm_t(PyObject *o, TRANSLATE_ENUM_WITH(fas_algorithm_tt); } +/** + * \ingroup python_interface_conversion + * \brief Converts a Python object to an igraph \c igraph_fvs_algorithm_t + */ +int igraphmodule_PyObject_to_fvs_algorithm_t(PyObject *o, + igraph_fas_algorithm_t *result) { + static igraphmodule_enum_translation_table_entry_t fvs_algorithm_tt[] = { + {"ip", IGRAPH_FVS_EXACT_IP}, + {0,0} + }; + TRANSLATE_ENUM_WITH(fvs_algorithm_tt); +} + /** * \ingroup python_interface_conversion * \brief Converts a Python object to an igraph \c igraph_get_adjacency_t diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 54094684c..22f28eb75 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -72,6 +72,7 @@ int igraphmodule_PyObject_to_community_comparison_t(PyObject *obj, int igraphmodule_PyObject_to_connectedness_t(PyObject *o, igraph_connectedness_t *result); int igraphmodule_PyObject_to_degseq_t(PyObject *o, igraph_degseq_t *result); int igraphmodule_PyObject_to_fas_algorithm_t(PyObject *o, igraph_fas_algorithm_t *result); +int igraphmodule_PyObject_to_fvs_algorithm_t(PyObject *o, igraph_fas_algorithm_t *result); int igraphmodule_PyObject_to_get_adjacency_t(PyObject *o, igraph_get_adjacency_t *result); int igraphmodule_PyObject_to_laplacian_normalization_t(PyObject *o, igraph_laplacian_normalization_t *result); int igraphmodule_PyObject_to_layout_grid_t(PyObject *o, igraph_layout_grid_t *result); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 9d696c905..bdcfd3d8c 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -5558,6 +5558,48 @@ PyObject *igraphmodule_Graph_feedback_arc_set( } +/** \ingroup python_interface_graph + * \brief Calculates a feedback vertex set for a graph + * \return a list containing the indices in the chosen feedback vertex set + * \sa igraph_feedback_vertex_set + */ +PyObject *igraphmodule_Graph_feedback_vertex_set( + igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = { "weights", "method", NULL }; + igraph_vector_t* weights = 0; + igraph_vector_int_t res; + igraph_fvs_algorithm_t algo = IGRAPH_FVS_EXACT_IP; + PyObject *weights_o = Py_None, *result_o = NULL, *algo_o = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &weights_o, &algo_o)) + return NULL; + + if (igraphmodule_PyObject_to_fvs_algorithm_t(algo_o, &algo)) + return NULL; + + if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, + ATTRIBUTE_TYPE_VERTEX)) + return NULL; + + if (igraph_vector_int_init(&res, 0)) { + if (weights) { igraph_vector_destroy(weights); free(weights); } + } + + if (igraph_feedback_vertex_set(&self->g, &res, weights, algo)) { + if (weights) { igraph_vector_destroy(weights); free(weights); } + igraph_vector_int_destroy(&res); + return NULL; + } + + if (weights) { igraph_vector_destroy(weights); free(weights); } + + result_o = igraphmodule_vector_int_t_to_PyList(&res); + igraph_vector_int_destroy(&res); + + return result_o; +} + + /** \ingroup python_interface_graph * \brief Calculates a single shortest path between a source and a target vertex * \return a list containing a single shortest path from the source to the target @@ -15451,6 +15493,23 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: the IDs of the edges to be removed, in a list.\n\n" }, + /* interface to igraph_feedback_vertex_set */ + {"feedback_vertex_set", (PyCFunction) igraphmodule_Graph_feedback_vertex_set, + METH_VARARGS | METH_KEYWORDS, + "feedback_vertex_set(weights=None, method=\"ip\")\n--\n\n" + "Calculates a minimum feedback vertex set.\n\n" + "A feedback vertex set is a set of edges whose removal makes the graph acyclic.\n" + "Finding a minimum feedback vertex set is an NP-hard problem both in directed\n" + "and undirected graphs.\n\n" + "@param weights: vertex weights to be used. Can be a sequence or iterable or\n" + " even a vertex attribute name. When given, the algorithm will strive to\n" + " remove lightweight vertices in order to minimize the total weight of the\n" + " feedback vertex set.\n" + "@param method: the algorithm to use. C{\"ip\"} uses an exact integer programming\n" + " approach, and is currently the only available method.\n" + "@return: the IDs of the vertices to be removed, in a list.\n\n" + }, + /* interface to igraph_get_shortest_path */ {"get_shortest_path", (PyCFunction) igraphmodule_Graph_get_shortest_path, METH_VARARGS | METH_KEYWORDS,