@@ -2169,6 +2169,57 @@ PyObject *igraphmodule_Graph_Bipartite(PyTypeObject * type,
2169
2169
return (PyObject *) self;
2170
2170
}
2171
2171
2172
+ /** \ingroup python_interface_graph
2173
+ * \brief Generates a Chung-Lu random graph
2174
+ * This is intended to be a class method in Python, so the first argument
2175
+ * is the type object and not the Python igraph object (because we have
2176
+ * to allocate that in this method).
2177
+ *
2178
+ * \return a reference to the newly generated Python igraph object
2179
+ * \sa igraph_chung_lu_game
2180
+ */
2181
+ PyObject *igraphmodule_Graph_Chung_Lu(PyTypeObject *type, PyObject *args, PyObject *kwds)
2182
+ {
2183
+ igraphmodule_GraphObject *self;
2184
+ igraph_t g;
2185
+ igraph_vector_t outw, inw;
2186
+ igraph_chung_lu_t var = IGRAPH_CHUNG_LU_ORIGINAL;
2187
+ igraph_bool_t has_inw = false;
2188
+ PyObject *weight_out = NULL, *weight_in = NULL, *loops = Py_True, *variant = NULL;
2189
+
2190
+ static char *kwlist[] = { "out", "in_", "loops", "variant", NULL };
2191
+
2192
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist,
2193
+ &weight_out, &weight_in, &loops, &variant))
2194
+ return NULL;
2195
+
2196
+ if (igraphmodule_PyObject_to_chung_lu_t(variant, &var)) return NULL;
2197
+ if (igraphmodule_PyObject_to_vector_t(weight_out, &outw, /* need_non_negative */ true)) return NULL;
2198
+ if (weight_in) {
2199
+ if (igraphmodule_PyObject_to_vector_t(weight_in, &inw, /* need_non_negative */ true)) {
2200
+ igraph_vector_destroy(&outw);
2201
+ return NULL;
2202
+ }
2203
+ has_inw=true;
2204
+ }
2205
+
2206
+ if (igraph_chung_lu_game(&g, &outw, has_inw ? &inw : NULL, PyObject_IsTrue(loops), var)) {
2207
+ igraphmodule_handle_igraph_error();
2208
+ igraph_vector_destroy(&outw);
2209
+ if (has_inw)
2210
+ igraph_vector_destroy(&inw);
2211
+ return NULL;
2212
+ }
2213
+
2214
+ igraph_vector_destroy(&outw);
2215
+ if (has_inw)
2216
+ igraph_vector_destroy(&inw);
2217
+
2218
+ CREATE_GRAPH_FROM_TYPE(self, g, type);
2219
+
2220
+ return (PyObject *) self;
2221
+ }
2222
+
2172
2223
/** \ingroup python_interface_graph
2173
2224
* \brief Generates a De Bruijn graph
2174
2225
* \sa igraph_kautz
@@ -14439,6 +14490,86 @@ struct PyMethodDef igraphmodule_Graph_methods[] = {
14439
14490
" this is the case, also its orientation. Must be one of\n"
14440
14491
" C{\"in\"}, C{\"out\"} and C{\"undirected\"}.\n"},
14441
14492
14493
+ /* interface to igraph_chung_lu_game */
14494
+ {"Chung_Lu", (PyCFunction) igraphmodule_Graph_Chung_Lu,
14495
+ METH_VARARGS | METH_CLASS | METH_KEYWORDS,
14496
+ "Chung_Lu(out, in_=None, loops=True, variant=\"original\")\n--\n\n"
14497
+ "Generates a Chung-Lu random graph.\n\n"
14498
+ "In the Chung-Lu model, each pair of vertices M{i} and M{j} is connected with\n"
14499
+ "independent probability M{p_{ij} = w_i w_j / S}, where M{w_i} is a weight\n"
14500
+ "associated with vertex M{i} and M{S = \\sum_k w_k} is the sum of weights.\n"
14501
+ "In the directed variant, vertices have both out-weights, M{w^\\text{out}},\n"
14502
+ "and in-weights, M{w^\\text{in}}, with equal sums,\n"
14503
+ "M{S = \\sum_k w^\\text{out}_k = \\sum_k w^\\text{in}_k}. The connection\n"
14504
+ "probability between M{i} and M{j} is M{p_{ij} = w^\\text{out}_i w^\\text{in}_j / S}.\n\n"
14505
+ "This model is commonly used to create random graphs with a fixed I{expected}\n"
14506
+ "degree sequence. The expected degree of vertex M{i} is approximately equal\n"
14507
+ "to the weight M{w_i}. Specifically, if the graph is directed and self-loops\n"
14508
+ "are allowed, then the expected out- and in-degrees are precisely M{w^\\text{out}}\n"
14509
+ "and M{w^\\text{in}}. If self-loops are disallowed, then the expected out-\n"
14510
+ "and in-degrees are M{w^\\text{out} (S - w^\\text{in}) / S} and\n"
14511
+ "M{w^\\text{in} (S - w^\\text{out}) / S}, respectively. If the graph is\n"
14512
+ "undirected, then the expected degrees with and without self-loops are\n"
14513
+ "M{w (S + w) / S} and M{w (S - w) / S}, respectively.\n\n"
14514
+ "A limitation of the original Chung-Lu model is that when some of the\n"
14515
+ "weights are large, the formula for M{p_{ij}} yields values larger than 1.\n"
14516
+ "Chung and Lu's original paper exludes the use of such weights. When\n"
14517
+ "M{p_{ij} > 1}, this function simply issues a warning and creates\n"
14518
+ "a connection between M{i} and M{j}. However, in this case the expected degrees\n"
14519
+ "will no longer relate to the weights in the manner stated above. Thus the\n"
14520
+ "original Chung-Lu model cannot produce certain (large) expected degrees.\n\n"
14521
+ "The overcome this limitation, this function implements additional variants of\n"
14522
+ "the model, with modified expressions for the connection probability M{p_{ij}}\n"
14523
+ "between vertices M{i} and M{j}. Let M{q_{ij} = w_i w_j / S}, or\n"
14524
+ "M{q_{ij} = w^out_i w^in_j / S} in the directed case. All model\n"
14525
+ "variants become equivalent in the limit of sparse graphs where M{q_{ij}}\n"
14526
+ "approaches zero. In the original Chung-Lu model, selectable by setting\n"
14527
+ "C{variant} to C{\"original\"}, M{p_{ij} = min(q_{ij}, 1)}.\n"
14528
+ "The C{\"grg\"} variant, often referred to a the generalized\n"
14529
+ "random graph, uses M{p_{ij} = q_{ij} / (1 + q_{ij})}, and is equivalent\n"
14530
+ "to a maximum entropy model (i.e. exponential random graph model) with\n"
14531
+ "a constraint on expected degrees, see Park and Newman (2004), Section B,\n"
14532
+ "setting M{exp(-\\Theta_{ij}) = w_i w_j / S}. This model is also\n"
14533
+ "discussed by Britton, Deijfen and Martin-Löf (2006). By virtue of being\n"
14534
+ "a degree-constrained maximum entropy model, it generates graphs having\n"
14535
+ "the same degree sequence with the same probability.\n"
14536
+ "A third variant can be requested with C{\"nr\"}, and uses\n"
14537
+ "M{p_{ij} = 1 - exp(-q_{ij})}. This is the underlying simple graph\n"
14538
+ "of a multigraph model introduced by Norros and Reittu (2006).\n"
14539
+ "For a discussion of these three model variants, see Section 16.4 of\n"
14540
+ "Bollobás, Janson, Riordan (2007), as well as Van Der Hofstad (2013).\n\n"
14541
+ "B{References:}\n\n"
14542
+ " - Chung F and Lu L: Connected components in a random graph with given degree sequences.\n"
14543
+ " I{Annals of Combinatorics} 6, 125-145 (2002) U{https://doi.org/10.1007/PL00012580}\n"
14544
+ " - Miller JC and Hagberg A: Efficient Generation of Networks with Given Expected Degrees (2011)\n"
14545
+ " U{https://doi.org/10.1007/978-3-642-21286-4_10}\n"
14546
+ " - Park J and Newman MEJ: Statistical mechanics of networks.\n"
14547
+ " I{Physical Review E} 70, 066117 (2004). U{https://doi.org/10.1103/PhysRevE.70.066117}\n"
14548
+ " - Britton T, Deijfen M, Martin-Löf A: Generating Simple Random Graphs with Prescribed Degree Distribution.\n"
14549
+ " I{J Stat Phys} 124, 1377–1397 (2006). U{https://doi.org/10.1007/s10955-006-9168-x}\n"
14550
+ " - Norros I and Reittu H: On a conditionally Poissonian graph process.\n"
14551
+ " I{Advances in Applied Probability} 38, 59–75 (2006).\n"
14552
+ " U{https://doi.org/10.1239/aap/1143936140}\n"
14553
+ " - Bollobás B, Janson S, Riordan O: The phase transition in inhomogeneous random graphs.\n"
14554
+ " I{Random Struct Algorithms} 31, 3–122 (2007). U{https://doi.org/10.1002/rsa.20168}\n"
14555
+ " - Van Der Hofstad R: Critical behavior in inhomogeneous random graphs.\n"
14556
+ " I{Random Struct Algorithms} 42, 480–508 (2013). U{https://doi.org/10.1002/rsa.20450}\n\n"
14557
+ "@param out: the vertex weights (or out-weights). In sparse graphs\n"
14558
+ " these will be approximately equal to the expected (out-)degrees.\n"
14559
+ "@param in_: the vertex in-weights, approximately equal to the expected\n"
14560
+ " in-degrees of the graph. If omitted, the generated graph will be\n"
14561
+ " undirected.\n"
14562
+ "@param loops: whether to allow the generation of self-loops.\n"
14563
+ "@param variant: the model variant to be used. Let M{q_{ij}=w_i w_j / S},\n"
14564
+ " where M{S = \\sum_k w_k}. The following variants are available:\n"
14565
+ " \n"
14566
+ " - C{\"original\"} -- the original Chung-Lu model with\n"
14567
+ " M{p_{ij} = min(1, q_{ij})}.\n"
14568
+ " - C{\"grg\"} -- generalized random graph, a maximum entropy model with\n"
14569
+ " a soft constraint on degrees, M{p_{ij} = q_{ij} / (1 + q_{ij})}\n"
14570
+ " - C{\"nr\"} -- Norros and Reittu's model, M{p_{ij} = 1 - exp(-q_{ij})}\n"
14571
+ },
14572
+
14442
14573
/* interface to igraph_degree_sequence_game */
14443
14574
{"Degree_Sequence", (PyCFunction) igraphmodule_Graph_Degree_Sequence,
14444
14575
METH_VARARGS | METH_CLASS | METH_KEYWORDS,
0 commit comments