Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/_igraph/convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,11 +600,26 @@ int igraphmodule_PyObject_to_fas_algorithm_t(PyObject *o,
{"exact", IGRAPH_FAS_EXACT_IP},
{"exact_ip", IGRAPH_FAS_EXACT_IP},
{"ip", IGRAPH_FAS_EXACT_IP},
{"ip_ti", IGRAPH_FAS_EXACT_IP_TI},
{"ip_cg", IGRAPH_FAS_EXACT_IP_CG},
{0,0}
};
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_fvs_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
Expand Down
1 change: 1 addition & 0 deletions src/_igraph/convert.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_fvs_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);
Expand Down
67 changes: 65 additions & 2 deletions src/_igraph/graphobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -15445,11 +15487,32 @@ struct PyMethodDef igraphmodule_Graph_methods[] = {
" breaking heuristic of Eades, Lin and Smyth, which is linear in the number\n"
" of edges but not necessarily optimal; however, it guarantees that the\n"
" number of edges to be removed is smaller than |E|/2 - |V|/6. C{\"ip\"} uses\n"
" an integer programming formulation which is guaranteed to yield an optimal\n"
" result, but is too slow for large graphs.\n"
" the most efficient available integer programming formulation which is guaranteed\n"
" to yield an optimal result. Specific integer programming formulations can be\n"
" selected using C{\"ip_ti\"} (using triangle inequalities) and C{\"ip_cg\"}\n"
" (a minimum set cover formulation using incremental constraint generation).\n"
" Note that the minimum feedback arc set problem is NP-hard, therefore all methods\n"
" that obtain exact optimal solutions are infeasibly slow on large graphs.\n"
"@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,
Expand Down
Loading