@@ -2975,6 +2975,61 @@ PyObject *igraphmodule_Graph_Realize_Degree_Sequence(PyTypeObject *type,
29752975}
29762976
29772977
2978+ /** \ingroup python_interface_graph
2979+ * \brief Generates a graph with a specified degree sequence
2980+ * \return a reference to the newly generated Python igraph object
2981+ * \sa igraph_realize_bipartite_degree_sequence
2982+ */
2983+ PyObject *igraphmodule_Graph_Realize_Bipartite_Degree_Sequence(PyTypeObject *type,
2984+ PyObject *args, PyObject *kwds) {
2985+
2986+ igraph_vector_int_t degrees1, degrees2;
2987+ igraph_edge_type_sw_t allowed_edge_types = IGRAPH_SIMPLE_SW;
2988+ igraph_realize_degseq_t method = IGRAPH_REALIZE_DEGSEQ_SMALLEST;
2989+ PyObject *degrees1_o, *degrees2_o;
2990+ PyObject *edge_types_o = Py_None, *method_o = Py_None;
2991+ igraphmodule_GraphObject *self;
2992+ igraph_t g;
2993+
2994+ static char *kwlist[] = { "degrees1", "degrees2", "allowed_edge_types", "method", NULL };
2995+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
2996+ °rees1_o, °rees2_o, &edge_types_o, &method_o))
2997+ return NULL;
2998+
2999+ /* allowed edge types */
3000+ if (igraphmodule_PyObject_to_edge_type_sw_t(edge_types_o, &allowed_edge_types))
3001+ return NULL;
3002+
3003+ /* methods */
3004+ if (igraphmodule_PyObject_to_realize_degseq_t(method_o, &method))
3005+ return NULL;
3006+
3007+ /* First degree vector */
3008+ if (igraphmodule_PyObject_to_vector_int_t(degrees1_o, °rees1))
3009+ return NULL;
3010+
3011+ /* Second degree vector */
3012+ if (igraphmodule_PyObject_to_vector_int_t(degrees2_o, °rees2)) {
3013+ igraph_vector_int_destroy(°rees1);
3014+ return NULL;
3015+ }
3016+
3017+ if (igraph_realize_bipartite_degree_sequence(&g, °rees1, °rees2, allowed_edge_types, method)) {
3018+ igraph_vector_int_destroy(°rees1);
3019+ igraph_vector_int_destroy(°rees2);
3020+ igraphmodule_handle_igraph_error();
3021+ return NULL;
3022+ }
3023+
3024+ igraph_vector_int_destroy(°rees1);
3025+ igraph_vector_int_destroy(°rees2);
3026+
3027+ CREATE_GRAPH_FROM_TYPE(self, g, type);
3028+
3029+ return (PyObject *) self;
3030+ }
3031+
3032+
29783033/** \ingroup python_interface_graph
29793034 * \brief Generates a graph based on vertex types and connection preferences
29803035 * \return a reference to the newly generated Python igraph object
@@ -14247,6 +14302,37 @@ struct PyMethodDef igraphmodule_Graph_methods[] = {
1424714302 " See Horvát and Modes (2021) for details.\n"
1424814303 },
1424914304
14305+ {"Realize_Bipartite_Degree_Sequence", (PyCFunction) igraphmodule_Graph_Realize_Bipartite_Degree_Sequence,
14306+ METH_VARARGS | METH_CLASS | METH_KEYWORDS,
14307+ "Realize_Bipartite_Degree_Sequence(degrees1, degrees2, allowed_edge_types=\"simple\", method=\"smallest\")\n--\n\n"
14308+ "Generates a bipartite graph from the degree sequences of its partitions.\n"
14309+ "\n"
14310+ "This method implements a Havel-Hakimi style graph construction for biparite\n"
14311+ "graphs. In each step, the algorithm picks two vertices in a deterministic\n"
14312+ "manner and connects them. The way the vertices are picked is defined by the\n"
14313+ "C{method} parameter. The allowed edge types (i.e. whether multi-edges are allowed)\n"
14314+ "are specified in the C{allowed_edge_types} parameter. Self-loops are never created,\n"
14315+ "since a graph with self-loops is not bipartite.\n"
14316+ "\n"
14317+ "@param degrees1: the degrees of the first partition.\n"
14318+ "@param degrees2: the degrees of the second partition.\n"
14319+ "@param allowed_edge_types: controls whether multi-edges are allowed\n"
14320+ " during the generation process. Possible values are:\n"
14321+ "\n"
14322+ " - C{\"simple\"}: simple graphs (no multi-edges)\n"
14323+ " - C{\"multi\"}: multi-edges allowed\n"
14324+ "\n"
14325+ "@param method: controls how the vertices are selected during the generation\n"
14326+ " process. Possible values are:\n"
14327+ "\n"
14328+ " - C{smallest}: The vertex with smallest remaining degree first.\n"
14329+ " - C{largest}: The vertex with the largest remaining degree first.\n"
14330+ " - C{index}: The vertices are selected in order of their index.\n"
14331+ "\n"
14332+ " The smallest C{smallest} method is guaranteed to produce a connected graph,\n"
14333+ " if one exists."
14334+ },
14335+
1425014336 // interface to igraph_ring
1425114337 {"Ring", (PyCFunction) igraphmodule_Graph_Ring,
1425214338 METH_VARARGS | METH_CLASS | METH_KEYWORDS,
0 commit comments